blob: df4fda9085302a6b74a34d889bfa05ca674123b7 [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"
Matt Menke4807a9a2020-11-21 00:14:4155#include "net/base/schemeful_site.h"
initial.commit586acc5fe2008-07-26 22:42:5256#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1557#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0658#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2159#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0860#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1161#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5362#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2463#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1264#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0065#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2966#include "net/http/http_auth_handler_ntlm.h"
Asanka Herathbf0b55d2019-12-07 03:27:0967#include "net/http/http_auth_ntlm_mechanism.h"
aberentbba302d2015-12-03 10:20:1968#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5769#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5270#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5671#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0472#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2473#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1374#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2675#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5776#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3877#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1978#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0779#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0080#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1981#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5182#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4683#include "net/log/test_net_log_util.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5684#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4085#include "net/proxy_resolution/mock_proxy_resolver.h"
86#include "net/proxy_resolution/proxy_config_service_fixed.h"
87#include "net/proxy_resolution/proxy_info.h"
88#include "net/proxy_resolution/proxy_resolver.h"
89#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4490#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1591#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0392#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3693#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4794#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0295#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0796#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0497#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4498#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1299#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:44100#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:58101#include "net/spdy/spdy_session.h"
102#include "net/spdy/spdy_session_pool.h"
103#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04104#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57105#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31106#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03107#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57108#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54109#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52110#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11111#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01112#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43113#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:40114#include "net/test/test_with_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14115#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23116#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00117#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44118#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06119#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18120#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52121#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15122#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27123#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52124
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37125#if defined(NTLM_PORTABLE)
126#include "base/base64.h"
127#include "net/ntlm/ntlm_test_data.h"
128#endif
129
Douglas Creager3cb042052018-11-06 23:08:52130#if BUILDFLAG(ENABLE_REPORTING)
131#include "net/network_error_logging/network_error_logging_service.h"
132#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14133#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10134#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14135#include "net/reporting/reporting_header_parser.h"
136#include "net/reporting/reporting_service.h"
137#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52138#endif // BUILDFLAG(ENABLE_REPORTING)
139
robpercival214763f2016-07-01 23:27:01140using net::test::IsError;
141using net::test::IsOk;
142
[email protected]ad65a3e2013-12-25 18:18:01143using base::ASCIIToUTF16;
144
David Benjamin3b94b0f2019-04-25 23:07:52145using testing::AnyOf;
Titouan Rigoudyba507a882020-07-31 12:15:15146using testing::ElementsAre;
147using testing::IsEmpty;
David Benjamin3b94b0f2019-04-25 23:07:52148
initial.commit586acc5fe2008-07-26 22:42:52149//-----------------------------------------------------------------------------
150
ttuttle859dc7a2015-04-23 19:42:29151namespace net {
152
[email protected]13c8a092010-07-29 06:15:44153namespace {
154
[email protected]42cba2fb2013-03-29 19:58:57155const base::string16 kBar(ASCIIToUTF16("bar"));
156const base::string16 kBar2(ASCIIToUTF16("bar2"));
157const base::string16 kBar3(ASCIIToUTF16("bar3"));
158const base::string16 kBaz(ASCIIToUTF16("baz"));
159const base::string16 kFirst(ASCIIToUTF16("first"));
160const base::string16 kFoo(ASCIIToUTF16("foo"));
161const base::string16 kFoo2(ASCIIToUTF16("foo2"));
162const base::string16 kFoo3(ASCIIToUTF16("foo3"));
163const base::string16 kFou(ASCIIToUTF16("fou"));
164const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57165const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44166
bnc2df4b522016-07-08 18:17:43167const char kAlternativeServiceHttpHeader[] =
168 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
169
ttuttle859dc7a2015-04-23 19:42:29170int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40171 return session
172 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
173 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29174 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02175}
176
ttuttle859dc7a2015-04-23 19:42:29177bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40178 return session
179 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
180 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29181 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52182}
183
[email protected]f3da152d2012-06-02 01:00:57184// Takes in a Value created from a NetLogHttpResponseParameter, and returns
185// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54186// of double quotes for easier comparison.
187std::string GetHeaders(const base::Value& params) {
188 if (!params.is_dict())
189 return "";
190 const base::Value* header_list = params.FindListKey("headers");
191 if (!header_list)
192 return "";
193 std::string headers;
194 base::JSONWriter::Write(*header_list, &headers);
195 base::ReplaceChars(headers, "\"", "'", &headers);
196 return headers;
[email protected]f3da152d2012-06-02 01:00:57197}
198
[email protected]029c83b62013-01-24 05:28:20199// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
200// used.
ttuttle859dc7a2015-04-23 19:42:29201void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20202 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19203 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25204
[email protected]029c83b62013-01-24 05:28:20205 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
206 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
207
ttuttle859dc7a2015-04-23 19:42:29208 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20209 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25210
211 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25212
[email protected]3b23a222013-05-15 21:33:25213 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25214 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
215 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25216 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25217}
218
[email protected]029c83b62013-01-24 05:28:20219// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
220// used.
ttuttle859dc7a2015-04-23 19:42:29221void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25222 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20223 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19224 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20225
226 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
227 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
228
ttuttle859dc7a2015-04-23 19:42:29229 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
230 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20231 EXPECT_LE(load_timing_info.connect_timing.connect_end,
232 load_timing_info.send_start);
233
234 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20235
[email protected]3b23a222013-05-15 21:33:25236 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20237 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
238 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25239 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20240}
241
242// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
243// used.
ttuttle859dc7a2015-04-23 19:42:29244void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20245 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19246 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20247
ttuttle859dc7a2015-04-23 19:42:29248 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20249
250 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
251 EXPECT_LE(load_timing_info.proxy_resolve_start,
252 load_timing_info.proxy_resolve_end);
253 EXPECT_LE(load_timing_info.proxy_resolve_end,
254 load_timing_info.send_start);
255 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20256
[email protected]3b23a222013-05-15 21:33:25257 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20258 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
259 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25260 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20261}
262
263// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
264// used.
ttuttle859dc7a2015-04-23 19:42:29265void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20266 int connect_timing_flags) {
267 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19268 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20269
270 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
271 EXPECT_LE(load_timing_info.proxy_resolve_start,
272 load_timing_info.proxy_resolve_end);
273 EXPECT_LE(load_timing_info.proxy_resolve_end,
274 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29275 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
276 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20277 EXPECT_LE(load_timing_info.connect_timing.connect_end,
278 load_timing_info.send_start);
279
280 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20281
[email protected]3b23a222013-05-15 21:33:25282 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20283 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
284 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25285 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25286}
287
Matt Menke2436b2f2018-12-11 18:07:11288// ProxyResolver that records URLs passed to it, and that can be told what
289// result to return.
290class CapturingProxyResolver : public ProxyResolver {
291 public:
Matt Menke8045afd2019-11-14 20:31:19292 struct LookupInfo {
293 GURL url;
294 NetworkIsolationKey network_isolation_key;
295 };
296
Matt Menke2436b2f2018-12-11 18:07:11297 CapturingProxyResolver()
298 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
299 ~CapturingProxyResolver() override = default;
300
301 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:39302 const NetworkIsolationKey& network_isolation_key,
Matt Menke2436b2f2018-12-11 18:07:11303 ProxyInfo* results,
304 CompletionOnceCallback callback,
305 std::unique_ptr<Request>* request,
306 const NetLogWithSource& net_log) override {
307 results->UseProxyServer(proxy_server_);
Matt Menke8045afd2019-11-14 20:31:19308 lookup_info_.push_back(LookupInfo{url, network_isolation_key});
Matt Menke2436b2f2018-12-11 18:07:11309 return OK;
310 }
311
312 // Sets whether the resolver should use direct connections, instead of a
313 // proxy.
314 void set_proxy_server(ProxyServer proxy_server) {
315 proxy_server_ = proxy_server;
316 }
317
Matt Menke8045afd2019-11-14 20:31:19318 const std::vector<LookupInfo>& lookup_info() const { return lookup_info_; }
Matt Menke2436b2f2018-12-11 18:07:11319
320 private:
Matt Menke8045afd2019-11-14 20:31:19321 std::vector<LookupInfo> lookup_info_;
Matt Menke2436b2f2018-12-11 18:07:11322
323 ProxyServer proxy_server_;
324
325 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
326};
327
328class CapturingProxyResolverFactory : public ProxyResolverFactory {
329 public:
330 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
331 : ProxyResolverFactory(false), resolver_(resolver) {}
332
333 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
334 std::unique_ptr<ProxyResolver>* resolver,
335 CompletionOnceCallback callback,
336 std::unique_ptr<Request>* request) override {
337 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
338 return OK;
339 }
340
341 private:
342 ProxyResolver* resolver_;
343};
344
danakj1fd259a02016-04-16 03:17:09345std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42346 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34347 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14348}
349
xunjieli96f2a402017-06-05 17:24:27350class FailingProxyResolverFactory : public ProxyResolverFactory {
351 public:
352 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
353
354 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42355 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
356 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17357 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42358 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27359 return ERR_PAC_SCRIPT_FAILED;
360 }
361};
362
Titouan Rigoudyba507a882020-07-31 12:15:15363// A default minimal HttpRequestInfo for use in tests, targeting HTTP.
Titouan Rigoudy78af7da2020-07-07 14:30:12364HttpRequestInfo DefaultRequestInfo() {
365 HttpRequestInfo info;
366 info.method = "GET";
Titouan Rigoudyba507a882020-07-31 12:15:15367 info.url = GURL("http://foo.test");
Titouan Rigoudy78af7da2020-07-07 14:30:12368 info.traffic_annotation =
369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
370 return info;
371}
372
Titouan Rigoudyba507a882020-07-31 12:15:15373// The default info for transports to the embedded HTTP server.
374TransportInfo EmbeddedHttpServerTransportInfo() {
375 TransportInfo info;
376 info.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 80);
377 return info;
378}
379
[email protected]448d4ca52012-03-04 04:12:23380} // namespace
381
Bence Béky98447b12018-05-08 03:14:01382class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05383 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03384 public:
bncd16676a2016-07-20 16:23:01385 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03386 // Important to restore the per-pool limit first, since the pool limit must
387 // always be greater than group limit, and the tests reduce both limits.
388 ClientSocketPoolManager::set_max_sockets_per_pool(
389 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
390 ClientSocketPoolManager::set_max_sockets_per_group(
391 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
392 }
393
[email protected]e3ceb682011-06-28 23:55:46394 protected:
[email protected]23e482282013-06-14 16:08:02395 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05396 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36397 dummy_connect_job_params_(
398 nullptr /* client_socket_factory */,
399 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40400 nullptr /* http_auth_cache */,
401 nullptr /* http_auth_handler_factory */,
402 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13403 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40404 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36405 nullptr /* proxy_delegate */,
406 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18407 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36408 nullptr /* socket_performance_watcher_factory */,
409 nullptr /* network_quality_estimator */,
410 nullptr /* net_log */,
411 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56412 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15413 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03414 HttpNetworkSession::NORMAL_SOCKET_POOL)),
415 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
416 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28417 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03418 }
[email protected]bb88e1d32013-05-03 23:11:07419
[email protected]e3ceb682011-06-28 23:55:46420 struct SimpleGetHelperResult {
421 int rv;
422 std::string status_line;
423 std::string response_data;
sclittlefb249892015-09-10 21:33:22424 int64_t total_received_bytes;
425 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25426 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47427 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59428 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46429 };
430
dcheng67be2b1f2014-10-27 21:47:29431 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50432 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55433 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56434 // Set an initial delay to ensure that the first call to TimeTicks::Now()
435 // before incrementing the counter does not return a null value.
Matt Menke6dc08232019-10-03 18:00:28436 FastForwardBy(base::TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54437 }
438
dcheng67be2b1f2014-10-27 21:47:29439 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50440 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55441 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09442 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55443 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09444 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50445 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55446 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09447 }
448
Andrew Comminos1f2ff1cc2018-12-14 05:22:38449 void Check100ResponseTiming(bool use_spdy);
450
[email protected]202965992011-12-07 23:04:51451 // Either |write_failure| specifies a write failure or |read_failure|
452 // specifies a read failure when using a reused socket. In either case, the
453 // failure should cause the network transaction to resend the request, and the
454 // other argument should be NULL.
455 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
456 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52457
[email protected]a34f61ee2014-03-18 20:59:49458 // Either |write_failure| specifies a write failure or |read_failure|
459 // specifies a read failure when using a reused socket. In either case, the
460 // failure should cause the network transaction to resend the request, and the
461 // other argument should be NULL.
462 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10463 const MockRead* read_failure,
Yoichi Osatof17bc892020-08-05 01:49:04464 bool use_spdy,
465 bool upload = false);
[email protected]a34f61ee2014-03-18 20:59:49466
Ryan Sleevib8d7ea02018-05-07 20:01:01467 SimpleGetHelperResult SimpleGetHelperForData(
468 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15469 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52470
[email protected]ff007e162009-05-23 09:13:15471 HttpRequestInfo request;
472 request.method = "GET";
bncce36dca22015-04-21 22:11:23473 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10474 request.traffic_annotation =
475 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52476
Matt Muellerd9342e3a2019-11-26 01:41:14477 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07478 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09479 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16480 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27481
Ryan Sleevib8d7ea02018-05-07 20:01:01482 for (auto* provider : providers) {
483 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29484 }
initial.commit586acc5fe2008-07-26 22:42:52485
[email protected]49639fa2011-12-20 23:22:41486 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52487
eroman24bc6a12015-05-06 19:55:48488 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16489 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01490 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52491
[email protected]ff007e162009-05-23 09:13:15492 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16493 out.total_received_bytes = trans.GetTotalReceivedBytes();
494 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25495
496 // Even in the failure cases that use this function, connections are always
497 // successfully established before the error.
bnc691fda62016-08-12 00:43:16498 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25499 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
500
[email protected]ff007e162009-05-23 09:13:15501 if (out.rv != OK)
502 return out;
503
bnc691fda62016-08-12 00:43:16504 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50505 // Can't use ASSERT_* inside helper functions like this, so
506 // return an error.
wezca1070932016-05-26 20:30:52507 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50508 out.rv = ERR_UNEXPECTED;
509 return out;
510 }
[email protected]ff007e162009-05-23 09:13:15511 out.status_line = response->headers->GetStatusLine();
512
Tsuyoshi Horo01faed62019-02-20 22:11:37513 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
514 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19515
ttuttled9dbc652015-09-29 20:00:59516 bool got_endpoint =
bnc691fda62016-08-12 00:43:16517 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59518 EXPECT_EQ(got_endpoint,
519 out.remote_endpoint_after_start.address().size() > 0);
520
bnc691fda62016-08-12 00:43:16521 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01522 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40523
Eric Roman79cc7552019-07-19 02:17:54524 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39525 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00526 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
527 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39528 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00529 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
530 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15531
Eric Roman79cc7552019-07-19 02:17:54532 EXPECT_EQ("GET / HTTP/1.1\r\n",
533 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57534
bncce36dca22015-04-21 22:11:23535 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54536 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40537
bnc691fda62016-08-12 00:43:16538 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22539 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16540 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22541
bnc691fda62016-08-12 00:43:16542 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47543 return out;
[email protected]ff007e162009-05-23 09:13:15544 }
initial.commit586acc5fe2008-07-26 22:42:52545
Ryan Sleevib8d7ea02018-05-07 20:01:01546 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22547 MockWrite data_writes[] = {
548 MockWrite("GET / HTTP/1.1\r\n"
549 "Host: www.example.org\r\n"
550 "Connection: keep-alive\r\n\r\n"),
551 };
[email protected]5a60c8b2011-10-19 20:14:29552
Ryan Sleevib8d7ea02018-05-07 20:01:01553 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22554 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01555 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22556
Ryan Sleevib8d7ea02018-05-07 20:01:01557 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22558 return out;
[email protected]b8015c42013-12-24 15:18:19559 }
560
bnc032658ba2016-09-26 18:17:15561 void AddSSLSocketData() {
562 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49563 ssl_.ssl_info.cert =
564 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
565 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
567 }
568
[email protected]ff007e162009-05-23 09:13:15569 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
570 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52571
[email protected]ff007e162009-05-23 09:13:15572 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07573
[email protected]bb88e1d32013-05-03 23:11:07574 void CheckErrorIsPassedBack(int error, IoMode mode);
575
David Benjaminbae08ba2019-10-18 21:06:15576 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
577 return base::BindRepeating(&HttpNetworkTransactionTest::FastForwardBy,
578 base::Unretained(this), delta);
579 }
580
Matt Menked6fd2a52019-03-20 06:14:36581 const CommonConnectJobParams dummy_connect_job_params_;
582
Matt Menkef437a87e2020-10-22 23:22:24583 const net::NetworkIsolationKey kNetworkIsolationKey =
Matt Menke4807a9a2020-11-21 00:14:41584 NetworkIsolationKey(SchemefulSite(GURL("https://foo.test/")),
585 SchemefulSite(GURL("https://bar.test/")));
Matt Menkef437a87e2020-10-22 23:22:24586
Douglas Creager134b52e2018-11-09 18:00:14587 // These clocks are defined here, even though they're only used in the
588 // Reporting tests below, since they need to be destroyed after
589 // |session_deps_|.
590 base::SimpleTestClock clock_;
591 base::SimpleTestTickClock tick_clock_;
592
[email protected]4bd46222013-05-14 19:32:23593 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07594 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15595 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03596
597 // Original socket limits. Some tests set these. Safest to always restore
598 // them once each test has been run.
599 int old_max_group_sockets_;
600 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15601};
[email protected]231d5a32008-09-13 00:45:27602
[email protected]448d4ca52012-03-04 04:12:23603namespace {
604
[email protected]15a5ccf82008-10-23 19:57:43605// Fill |str| with a long header list that consumes >= |size| bytes.
606void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51607 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19608 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
609 const int sizeof_row = strlen(row);
610 const int num_rows = static_cast<int>(
611 ceil(static_cast<float>(size) / sizeof_row));
612 const int sizeof_data = num_rows * sizeof_row;
613 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43614 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51615
[email protected]4ddaf2502008-10-23 18:26:19616 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43617 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19618}
619
thakis84dff942015-07-28 20:47:38620#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09621uint64_t MockGetMSTime() {
622 // Tue, 23 May 2017 20:13:07 +0000
623 return 131400439870000000;
624}
625
[email protected]385a4672009-03-11 22:21:29626// Alternative functions that eliminate randomness and dependency on the local
627// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37628void MockGenerateRandom(uint8_t* output, size_t n) {
629 // This is set to 0xaa because the client challenge for testing in
630 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
631 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29632}
633
[email protected]fe2bc6a2009-03-23 16:52:20634std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37635 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29636}
thakis84dff942015-07-28 20:47:38637#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29638
Matt Menked6fd2a52019-03-20 06:14:36639class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31640 public:
Matt Menked6fd2a52019-03-20 06:14:36641 explicit CaptureGroupIdTransportSocketPool(
642 const CommonConnectJobParams* common_connect_job_params)
643 : TransportClientSocketPool(0,
644 0,
645 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36646 ProxyServer::Direct(),
647 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52648 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18649
Matt Menkef6edce752019-03-19 17:21:56650 const ClientSocketPool::GroupId& last_group_id_received() const {
651 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49652 }
653
Tarun Bansal162eabe52018-01-20 01:16:39654 bool socket_requested() const { return socket_requested_; }
655
Matt Menke28ac03e2019-02-25 22:25:50656 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56657 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03658 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28659 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50660 RequestPriority priority,
661 const SocketTag& socket_tag,
662 ClientSocketPool::RespectLimits respect_limits,
663 ClientSocketHandle* handle,
664 CompletionOnceCallback callback,
665 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
666 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56667 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39668 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31669 return ERR_IO_PENDING;
670 }
Matt Menkef6edce752019-03-19 17:21:56671 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21672 ClientSocketHandle* handle,
673 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56674 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09675 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24676 int64_t generation) override {}
Matt Menke433de6d2020-03-04 00:24:11677 void CloseIdleSockets(const char* net_log_reason_utf8) override {}
678 void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
679 const char* net_log_reason_utf8) override {}
dmichaeld6e570d2014-12-18 22:30:57680 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56681 size_t IdleSocketCountInGroup(
682 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31683 return 0;
684 }
Matt Menkef6edce752019-03-19 17:21:56685 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57686 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31687 return LOAD_STATE_IDLE;
688 }
[email protected]d80a4322009-08-14 07:07:49689
690 private:
Matt Menkef6edce752019-03-19 17:21:56691 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39692 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31693};
694
[email protected]231d5a32008-09-13 00:45:27695//-----------------------------------------------------------------------------
696
[email protected]79cb5c12011-09-12 13:12:04697// Helper functions for validating that AuthChallengeInfo's are correctly
698// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58699bool CheckBasicServerAuth(
700 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04701 if (!auth_challenge)
702 return false;
703 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43704 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04705 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19706 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04707 return true;
708}
709
David Benjamin2eb827f2019-04-29 18:31:04710bool CheckBasicSecureServerAuth(
711 const base::Optional<AuthChallengeInfo>& auth_challenge) {
712 if (!auth_challenge)
713 return false;
714 EXPECT_FALSE(auth_challenge->is_proxy);
715 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
716 EXPECT_EQ("MyRealm1", auth_challenge->realm);
717 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
718 return true;
719}
720
Emily Starkf2c9bbd2019-04-09 17:08:58721bool CheckBasicProxyAuth(
722 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04723 if (!auth_challenge)
724 return false;
725 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43726 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
727 EXPECT_EQ("MyRealm1", auth_challenge->realm);
728 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
729 return true;
730}
731
Emily Starkf2c9bbd2019-04-09 17:08:58732bool CheckBasicSecureProxyAuth(
733 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43734 if (!auth_challenge)
735 return false;
736 EXPECT_TRUE(auth_challenge->is_proxy);
737 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04738 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19739 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04740 return true;
741}
742
Emily Starkf2c9bbd2019-04-09 17:08:58743bool CheckDigestServerAuth(
744 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04745 if (!auth_challenge)
746 return false;
747 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43748 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04749 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19750 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04751 return true;
752}
753
thakis84dff942015-07-28 20:47:38754#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58755bool CheckNTLMServerAuth(
756 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04757 if (!auth_challenge)
758 return false;
759 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55760 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04761 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19762 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04763 return true;
764}
David Benjamin5cb91132018-04-06 05:54:49765
Emily Starkf2c9bbd2019-04-09 17:08:58766bool CheckNTLMProxyAuth(
767 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49768 if (!auth_challenge)
769 return false;
770 EXPECT_TRUE(auth_challenge->is_proxy);
771 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
772 EXPECT_EQ(std::string(), auth_challenge->realm);
773 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
774 return true;
775}
thakis84dff942015-07-28 20:47:38776#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04777
[email protected]448d4ca52012-03-04 04:12:23778} // namespace
779
bncd16676a2016-07-20 16:23:01780TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27783}
784
bncd16676a2016-07-20 16:23:01785TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27786 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35787 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
788 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06789 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27790 };
Ryan Sleevib8d7ea02018-05-07 20:01:01791 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01792 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27793 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
794 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01795 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22796 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47797 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59798
799 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27800}
801
802// Response with no status line.
bncd16676a2016-07-20 16:23:01803TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27804 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35805 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06806 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27807 };
Ryan Sleevib8d7ea02018-05-07 20:01:01808 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41809 EXPECT_THAT(out.rv, IsOk());
810 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
811 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01812 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41813 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27814}
815
mmenkea7da6da2016-09-01 21:56:52816// Response with no status line, and a weird port. Should fail by default.
817TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
818 MockRead data_reads[] = {
819 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
820 };
821
Ryan Sleevib8d7ea02018-05-07 20:01:01822 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52823 session_deps_.socket_factory->AddSocketDataProvider(&data);
824
825 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
826
krasinc06a72a2016-12-21 03:42:46827 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58828 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19829 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52830
mmenkea7da6da2016-09-01 21:56:52831 request.method = "GET";
832 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e2018-02-07 07:41:10833 request.traffic_annotation =
834 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
835
mmenkea7da6da2016-09-01 21:56:52836 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20837 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52838 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
839}
840
Shivani Sharmafdcaefd2017-11-02 00:12:26841// Tests that request info can be destroyed after the headers phase is complete.
842TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
843 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
844 auto trans =
845 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
846
847 MockRead data_reads[] = {
848 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
849 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
850 };
Ryan Sleevib8d7ea02018-05-07 20:01:01851 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26852 session_deps_.socket_factory->AddSocketDataProvider(&data);
853
854 TestCompletionCallback callback;
855
856 {
857 auto request = std::make_unique<HttpRequestInfo>();
858 request->method = "GET";
859 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10860 request->traffic_annotation =
861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26862
863 int rv =
864 trans->Start(request.get(), callback.callback(), NetLogWithSource());
865
866 EXPECT_THAT(callback.GetResult(rv), IsOk());
867 } // Let request info be destroyed.
868
869 trans.reset();
870}
871
dalyk6d7a8c52019-12-18 21:43:01872// Test that a failure in resolving the hostname is retrievable.
873TEST_F(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
874 HttpRequestInfo request;
875 request.method = "GET";
876 request.url = GURL("http://www.example.org/");
877 request.traffic_annotation =
878 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
879
880 RecordingTestNetLog log;
881 MockHostResolver* resolver = new MockHostResolver();
882 resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
883 session_deps_.net_log = &log;
884 session_deps_.host_resolver.reset(resolver);
885 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
886 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
887 TestCompletionCallback callback;
888
889 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
890 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
891 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
892
893 const HttpResponseInfo* response = trans.GetResponseInfo();
894 ASSERT_TRUE(response);
895 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
896}
897
Titouan Rigoudy78af7da2020-07-07 14:30:12898// This test verifies that if the transaction fails before even connecting to a
899// remote endpoint, the ConnectedCallback is never called.
900TEST_F(HttpNetworkTransactionTest, ConnectedCallbackNeverCalled) {
901 auto resolver = std::make_unique<MockHostResolver>();
Titouan Rigoudyba507a882020-07-31 12:15:15902 resolver->rules()->AddSimulatedTimeoutFailure("bar.test");
Titouan Rigoudy78af7da2020-07-07 14:30:12903 session_deps_.host_resolver = std::move(resolver);
904
905 ConnectedHandler connected_handler;
906 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
Titouan Rigoudyba507a882020-07-31 12:15:15907
Titouan Rigoudy78af7da2020-07-07 14:30:12908 auto request = DefaultRequestInfo();
Titouan Rigoudyba507a882020-07-31 12:15:15909 request.url = GURL("http://bar.test");
910
Titouan Rigoudy78af7da2020-07-07 14:30:12911 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
912 transaction.SetConnectedCallback(connected_handler.Callback());
913
914 TestCompletionCallback callback;
915 transaction.Start(&request, callback.callback(), NetLogWithSource());
916 callback.WaitForResult();
917
Titouan Rigoudyba507a882020-07-31 12:15:15918 EXPECT_THAT(connected_handler.transports(), IsEmpty());
Titouan Rigoudy78af7da2020-07-07 14:30:12919}
920
921// This test verifies that if the ConnectedCallback returns an error, the
922// entire transaction fails with that error.
923TEST_F(HttpNetworkTransactionTest, ConnectedCallbackFailure) {
924 // The exact error code does not matter, as long as it is the same one
925 // returned by the transaction overall.
926 ConnectedHandler connected_handler;
927 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
928
929 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
930 auto request = DefaultRequestInfo();
931 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
932 transaction.SetConnectedCallback(connected_handler.Callback());
933
934 // We never get to writing any data, but we still need a socket.
935 StaticSocketDataProvider data;
936 session_deps_.socket_factory->AddSocketDataProvider(&data);
937
938 TestCompletionCallback callback;
939 EXPECT_THAT(
940 transaction.Start(&request, callback.callback(), NetLogWithSource()),
941 IsError(ERR_IO_PENDING));
942 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
943
Titouan Rigoudyba507a882020-07-31 12:15:15944 EXPECT_THAT(connected_handler.transports(),
945 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:12946}
947
948// This test verifies that the ConnectedCallback is called once in the case of
949// simple requests.
950TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnce) {
951 MockRead data_reads[] = {
952 MockRead("HTTP/1.0 200 OK\r\n"),
953 MockRead(SYNCHRONOUS, OK),
954 };
955 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
956 session_deps_.socket_factory->AddSocketDataProvider(&data);
957
958 ConnectedHandler connected_handler;
959 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
960 auto request = DefaultRequestInfo();
961 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
962 transaction.SetConnectedCallback(connected_handler.Callback());
963
964 TestCompletionCallback callback;
965 EXPECT_THAT(
966 transaction.Start(&request, callback.callback(), NetLogWithSource()),
967 IsError(ERR_IO_PENDING));
968 EXPECT_THAT(callback.WaitForResult(), IsOk());
969
Titouan Rigoudyba507a882020-07-31 12:15:15970 EXPECT_THAT(connected_handler.transports(),
971 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:12972}
973
974// This test verifies that the ConnectedCallback is called once more per
975// authentication challenge.
976TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachAuthChallenge) {
977 ConnectedHandler connected_handler;
978 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
979 auto request = DefaultRequestInfo();
980 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
981 transaction.SetConnectedCallback(connected_handler.Callback());
982
983 // First request receives an auth challenge.
984 MockRead data_reads1[] = {
985 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
986 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
987 MockRead(SYNCHRONOUS, ERR_FAILED),
988 };
989 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
990 session_deps_.socket_factory->AddSocketDataProvider(&data1);
991
992 // Second request is allowed through.
993 MockRead data_reads2[] = {
994 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
995 MockRead(SYNCHRONOUS, OK),
996 };
997 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
998 session_deps_.socket_factory->AddSocketDataProvider(&data2);
999
1000 // First request, connects once.
1001 TestCompletionCallback callback1;
1002 EXPECT_THAT(
1003 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1004 IsError(ERR_IO_PENDING));
1005 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1006
Titouan Rigoudyba507a882020-07-31 12:15:151007 EXPECT_THAT(connected_handler.transports(),
1008 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121009
1010 // Second request, connects again.
1011 TestCompletionCallback callback2;
1012 EXPECT_THAT(transaction.RestartWithAuth(AuthCredentials(kFoo, kBar),
1013 callback2.callback()),
1014 IsError(ERR_IO_PENDING));
1015 EXPECT_THAT(callback2.WaitForResult(), IsOk());
1016
Titouan Rigoudyba507a882020-07-31 12:15:151017 EXPECT_THAT(connected_handler.transports(),
1018 ElementsAre(EmbeddedHttpServerTransportInfo(),
1019 EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121020}
1021
1022// This test verifies that the ConnectedCallback is called once more per retry.
1023TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachRetry) {
1024 ConnectedHandler connected_handler;
1025 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1026 auto request = DefaultRequestInfo();
1027 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1028 transaction.SetConnectedCallback(connected_handler.Callback());
1029
1030 // First request receives a retryable error.
1031 MockRead data_reads1[] = {
1032 MockRead(SYNCHRONOUS, ERR_HTTP2_SERVER_REFUSED_STREAM),
1033 };
1034 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
1035 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1036
1037 // Second request is allowed through.
1038 MockRead data_reads2[] = {
1039 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1040 MockRead(SYNCHRONOUS, OK),
1041 };
1042 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
1043 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1044
1045 TestCompletionCallback callback1;
1046 EXPECT_THAT(
1047 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1048 IsError(ERR_IO_PENDING));
1049 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1050
Titouan Rigoudyba507a882020-07-31 12:15:151051 EXPECT_THAT(connected_handler.transports(),
1052 ElementsAre(EmbeddedHttpServerTransportInfo(),
1053 EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121054}
1055
[email protected]231d5a32008-09-13 00:45:271056// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:011057TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:271058 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351059 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061060 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271061 };
Ryan Sleevib8d7ea02018-05-07 20:01:011062 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011063 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:271064 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1065 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011066 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221067 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271068}
1069
1070// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:011071TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:271072 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351073 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061074 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271075 };
Ryan Sleevib8d7ea02018-05-07 20:01:011076 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011077 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:271078 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1079 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011080 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221081 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271082}
1083
1084// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:011085TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:271086 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351087 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:061088 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271089 };
Ryan Sleevib8d7ea02018-05-07 20:01:011090 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411091 EXPECT_THAT(out.rv, IsOk());
1092 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1093 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011094 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411095 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271096}
1097
1098// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:011099TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:271100 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351101 MockRead("\n"),
1102 MockRead("\n"),
1103 MockRead("Q"),
1104 MockRead("J"),
1105 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061106 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271107 };
Ryan Sleevib8d7ea02018-05-07 20:01:011108 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011109 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:271110 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1111 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011112 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221113 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271114}
1115
1116// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:011117TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:271118 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351119 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:061120 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271121 };
Ryan Sleevib8d7ea02018-05-07 20:01:011122 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411123 EXPECT_THAT(out.rv, IsOk());
1124 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1125 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011126 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411127 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:521128}
1129
[email protected]f9d44aa2008-09-23 23:57:171130// Simulate a 204 response, lacking a Content-Length header, sent over a
1131// persistent connection. The response should still terminate since a 204
1132// cannot have a response body.
bncd16676a2016-07-20 16:23:011133TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:191134 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:171135 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351136 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:191137 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:061138 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:171139 };
Ryan Sleevib8d7ea02018-05-07 20:01:011140 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011141 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171142 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1143 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011144 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221145 int64_t response_size = reads_size - strlen(junk);
1146 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171147}
1148
[email protected]0877e3d2009-10-17 22:29:571149// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011150TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191151 std::string final_chunk = "0\r\n\r\n";
1152 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1153 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571154 MockRead data_reads[] = {
1155 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1156 MockRead("5\r\nHello\r\n"),
1157 MockRead("1\r\n"),
1158 MockRead(" \r\n"),
1159 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191160 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061161 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571162 };
Ryan Sleevib8d7ea02018-05-07 20:01:011163 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011164 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571165 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1166 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011167 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221168 int64_t response_size = reads_size - extra_data.size();
1169 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571170}
1171
[email protected]9fe44f52010-09-23 18:36:001172// Next tests deal with http://crbug.com/56344.
1173
bncd16676a2016-07-20 16:23:011174TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001175 MultipleContentLengthHeadersNoTransferEncoding) {
1176 MockRead data_reads[] = {
1177 MockRead("HTTP/1.1 200 OK\r\n"),
1178 MockRead("Content-Length: 10\r\n"),
1179 MockRead("Content-Length: 5\r\n\r\n"),
1180 };
Ryan Sleevib8d7ea02018-05-07 20:01:011181 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011182 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001183}
1184
bncd16676a2016-07-20 16:23:011185TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041186 DuplicateContentLengthHeadersNoTransferEncoding) {
1187 MockRead data_reads[] = {
1188 MockRead("HTTP/1.1 200 OK\r\n"),
1189 MockRead("Content-Length: 5\r\n"),
1190 MockRead("Content-Length: 5\r\n\r\n"),
1191 MockRead("Hello"),
1192 };
Ryan Sleevib8d7ea02018-05-07 20:01:011193 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011194 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041195 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1196 EXPECT_EQ("Hello", out.response_data);
1197}
1198
bncd16676a2016-07-20 16:23:011199TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041200 ComplexContentLengthHeadersNoTransferEncoding) {
1201 // More than 2 dupes.
1202 {
1203 MockRead data_reads[] = {
1204 MockRead("HTTP/1.1 200 OK\r\n"),
1205 MockRead("Content-Length: 5\r\n"),
1206 MockRead("Content-Length: 5\r\n"),
1207 MockRead("Content-Length: 5\r\n\r\n"),
1208 MockRead("Hello"),
1209 };
Ryan Sleevib8d7ea02018-05-07 20:01:011210 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011211 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041212 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1213 EXPECT_EQ("Hello", out.response_data);
1214 }
1215 // HTTP/1.0
1216 {
1217 MockRead data_reads[] = {
1218 MockRead("HTTP/1.0 200 OK\r\n"),
1219 MockRead("Content-Length: 5\r\n"),
1220 MockRead("Content-Length: 5\r\n"),
1221 MockRead("Content-Length: 5\r\n\r\n"),
1222 MockRead("Hello"),
1223 };
Ryan Sleevib8d7ea02018-05-07 20:01:011224 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011225 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041226 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1227 EXPECT_EQ("Hello", out.response_data);
1228 }
1229 // 2 dupes and one mismatched.
1230 {
1231 MockRead data_reads[] = {
1232 MockRead("HTTP/1.1 200 OK\r\n"),
1233 MockRead("Content-Length: 10\r\n"),
1234 MockRead("Content-Length: 10\r\n"),
1235 MockRead("Content-Length: 5\r\n\r\n"),
1236 };
Ryan Sleevib8d7ea02018-05-07 20:01:011237 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011238 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041239 }
1240}
1241
bncd16676a2016-07-20 16:23:011242TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001243 MultipleContentLengthHeadersTransferEncoding) {
1244 MockRead data_reads[] = {
1245 MockRead("HTTP/1.1 200 OK\r\n"),
1246 MockRead("Content-Length: 666\r\n"),
1247 MockRead("Content-Length: 1337\r\n"),
1248 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1249 MockRead("5\r\nHello\r\n"),
1250 MockRead("1\r\n"),
1251 MockRead(" \r\n"),
1252 MockRead("5\r\nworld\r\n"),
1253 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061254 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001255 };
Ryan Sleevib8d7ea02018-05-07 20:01:011256 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011257 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001258 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1259 EXPECT_EQ("Hello world", out.response_data);
1260}
1261
[email protected]1628fe92011-10-04 23:04:551262// Next tests deal with http://crbug.com/98895.
1263
1264// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011265TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551266 MockRead data_reads[] = {
1267 MockRead("HTTP/1.1 200 OK\r\n"),
1268 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1269 MockRead("Content-Length: 5\r\n\r\n"),
1270 MockRead("Hello"),
1271 };
Ryan Sleevib8d7ea02018-05-07 20:01:011272 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011273 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551274 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1275 EXPECT_EQ("Hello", out.response_data);
1276}
1277
[email protected]54a9c6e52012-03-21 20:10:591278// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011279TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551280 MockRead data_reads[] = {
1281 MockRead("HTTP/1.1 200 OK\r\n"),
1282 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1283 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1284 MockRead("Content-Length: 5\r\n\r\n"),
1285 MockRead("Hello"),
1286 };
Ryan Sleevib8d7ea02018-05-07 20:01:011287 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011288 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591289 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1290 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551291}
1292
1293// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011294TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551295 MockRead data_reads[] = {
1296 MockRead("HTTP/1.1 200 OK\r\n"),
1297 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1298 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1299 MockRead("Content-Length: 5\r\n\r\n"),
1300 MockRead("Hello"),
1301 };
Ryan Sleevib8d7ea02018-05-07 20:01:011302 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011303 EXPECT_THAT(out.rv,
1304 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551305}
1306
[email protected]54a9c6e52012-03-21 20:10:591307// Checks that two identical Location headers result in no error.
1308// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011309TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551310 MockRead data_reads[] = {
1311 MockRead("HTTP/1.1 302 Redirect\r\n"),
1312 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591313 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551314 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061315 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551316 };
1317
1318 HttpRequestInfo request;
1319 request.method = "GET";
1320 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101321 request.traffic_annotation =
1322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551323
danakj1fd259a02016-04-16 03:17:091324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161325 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551326
Ryan Sleevib8d7ea02018-05-07 20:01:011327 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071328 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551329
[email protected]49639fa2011-12-20 23:22:411330 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551331
tfarina42834112016-09-22 13:38:201332 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551334
robpercival214763f2016-07-01 23:27:011335 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551336
bnc691fda62016-08-12 00:43:161337 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521338 ASSERT_TRUE(response);
1339 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551340 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1341 std::string url;
1342 EXPECT_TRUE(response->headers->IsRedirect(&url));
1343 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471344 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551345}
1346
[email protected]1628fe92011-10-04 23:04:551347// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011348TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551349 MockRead data_reads[] = {
1350 MockRead("HTTP/1.1 302 Redirect\r\n"),
1351 MockRead("Location: http://good.com/\r\n"),
1352 MockRead("Location: http://evil.com/\r\n"),
1353 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061354 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551355 };
Ryan Sleevib8d7ea02018-05-07 20:01:011356 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011357 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551358}
1359
[email protected]ef0faf2e72009-03-05 23:27:231360// Do a request using the HEAD method. Verify that we don't try to read the
1361// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011362TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421363 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231364 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231365 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101366 request.traffic_annotation =
1367 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231368
danakj1fd259a02016-04-16 03:17:091369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:121371 ConnectedHandler connected_handler;
1372 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]cb9bf6ca2011-01-28 13:15:271373
[email protected]ef0faf2e72009-03-05 23:27:231374 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131375 MockWrite("HEAD / HTTP/1.1\r\n"
1376 "Host: www.example.org\r\n"
1377 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231378 };
1379 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231380 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1381 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231382
mmenked39192ee2015-12-09 00:57:231383 // No response body because the test stops reading here.
1384 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231385 };
1386
Ryan Sleevib8d7ea02018-05-07 20:01:011387 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071388 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231389
[email protected]49639fa2011-12-20 23:22:411390 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231391
tfarina42834112016-09-22 13:38:201392 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231394
1395 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011396 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231397
bnc691fda62016-08-12 00:43:161398 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521399 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231400
1401 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521402 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231403 EXPECT_EQ(1234, response->headers->GetContentLength());
1404 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471405 EXPECT_TRUE(response->proxy_server.is_direct());
Titouan Rigoudyba507a882020-07-31 12:15:151406 EXPECT_THAT(connected_handler.transports(),
1407 ElementsAre(EmbeddedHttpServerTransportInfo()));
[email protected]ef0faf2e72009-03-05 23:27:231408
1409 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101410 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231411 bool has_server_header = response->headers->EnumerateHeader(
1412 &iter, "Server", &server_header);
1413 EXPECT_TRUE(has_server_header);
1414 EXPECT_EQ("Blah", server_header);
1415
1416 // Reading should give EOF right away, since there is no message body
1417 // (despite non-zero content-length).
1418 std::string response_data;
bnc691fda62016-08-12 00:43:161419 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011420 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231421 EXPECT_EQ("", response_data);
1422}
1423
bncd16676a2016-07-20 16:23:011424TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091425 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521426
1427 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351428 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1429 MockRead("hello"),
1430 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1431 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061432 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521433 };
Ryan Sleevib8d7ea02018-05-07 20:01:011434 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071435 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521436
[email protected]0b0bf032010-09-21 18:08:501437 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521438 "hello", "world"
1439 };
1440
1441 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421442 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521443 request.method = "GET";
bncce36dca22015-04-21 22:11:231444 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101445 request.traffic_annotation =
1446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521447
bnc691fda62016-08-12 00:43:161448 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271449
[email protected]49639fa2011-12-20 23:22:411450 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521451
tfarina42834112016-09-22 13:38:201452 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011453 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521454
1455 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011456 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521457
bnc691fda62016-08-12 00:43:161458 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521459 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521460
wezca1070932016-05-26 20:30:521461 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471463 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521464
1465 std::string response_data;
bnc691fda62016-08-12 00:43:161466 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011467 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251468 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521469 }
1470}
1471
bncd16676a2016-07-20 16:23:011472TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091473 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221474 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191475 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221476 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271477
[email protected]1c773ea12009-04-28 19:58:421478 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521479 request.method = "POST";
1480 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271481 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:101482 request.traffic_annotation =
1483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521484
shivanishab9a143952016-09-19 17:23:411485 // Check the upload progress returned before initialization is correct.
1486 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1487 EXPECT_EQ(0u, progress.size());
1488 EXPECT_EQ(0u, progress.position());
1489
danakj1fd259a02016-04-16 03:17:091490 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161491 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271492
initial.commit586acc5fe2008-07-26 22:42:521493 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351494 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1495 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1496 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061497 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521498 };
Ryan Sleevib8d7ea02018-05-07 20:01:011499 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071500 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521501
[email protected]49639fa2011-12-20 23:22:411502 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521503
tfarina42834112016-09-22 13:38:201504 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011505 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521506
1507 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011508 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521509
bnc691fda62016-08-12 00:43:161510 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521511 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521512
wezca1070932016-05-26 20:30:521513 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251514 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521515
1516 std::string response_data;
bnc691fda62016-08-12 00:43:161517 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011518 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251519 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521520}
1521
[email protected]3a2d3662009-03-27 03:49:141522// This test is almost the same as Ignores100 above, but the response contains
1523// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571524// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011525TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421526 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141527 request.method = "GET";
1528 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101529 request.traffic_annotation =
1530 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141531
danakj1fd259a02016-04-16 03:17:091532 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161533 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271534
[email protected]3a2d3662009-03-27 03:49:141535 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571536 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1537 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141538 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061539 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141540 };
Ryan Sleevib8d7ea02018-05-07 20:01:011541 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071542 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141543
[email protected]49639fa2011-12-20 23:22:411544 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141545
tfarina42834112016-09-22 13:38:201546 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011547 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141548
1549 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011550 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141551
bnc691fda62016-08-12 00:43:161552 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521553 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141554
wezca1070932016-05-26 20:30:521555 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141556 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1557
1558 std::string response_data;
bnc691fda62016-08-12 00:43:161559 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011560 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141561 EXPECT_EQ("hello world", response_data);
1562}
1563
Andrew Comminos517a92c2019-01-14 17:49:561564TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1565 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381566 base::TimeDelta::FromMilliseconds(10);
1567
1568 HttpRequestInfo request;
1569 request.method = "GET";
1570 request.url = GURL("http://www.foo.com/");
1571 request.traffic_annotation =
1572 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1573
1574 std::vector<MockWrite> data_writes = {
1575 MockWrite(ASYNC, 0,
1576 "GET / HTTP/1.1\r\n"
1577 "Host: www.foo.com\r\n"
1578 "Connection: keep-alive\r\n\r\n"),
1579 };
1580
1581 std::vector<MockRead> data_reads = {
1582 // Write one byte of the status line, followed by a pause.
1583 MockRead(ASYNC, 1, "H"),
1584 MockRead(ASYNC, ERR_IO_PENDING, 2),
1585 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1586 MockRead(ASYNC, 4, "hello world"),
1587 MockRead(SYNCHRONOUS, OK, 5),
1588 };
1589
1590 SequencedSocketData data(data_reads, data_writes);
1591 session_deps_.socket_factory->AddSocketDataProvider(&data);
1592
1593 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1594
1595 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1596
1597 TestCompletionCallback callback;
1598
1599 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1600 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1601
1602 data.RunUntilPaused();
1603 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561604 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381605 data.Resume();
1606
1607 rv = callback.WaitForResult();
1608 EXPECT_THAT(rv, IsOk());
1609
1610 const HttpResponseInfo* response = trans.GetResponseInfo();
1611 ASSERT_TRUE(response);
1612
1613 EXPECT_TRUE(response->headers);
1614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1615
1616 LoadTimingInfo load_timing_info;
1617 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1618 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1619 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561620 // Ensure we didn't include the delay in the TTFB time.
1621 EXPECT_EQ(load_timing_info.receive_headers_start,
1622 load_timing_info.connect_timing.connect_end);
1623 // Ensure that the mock clock advanced at all.
1624 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1625 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381626
1627 std::string response_data;
1628 rv = ReadTransaction(&trans, &response_data);
1629 EXPECT_THAT(rv, IsOk());
1630 EXPECT_EQ("hello world", response_data);
1631}
1632
1633// Tests that the time-to-first-byte reported in a transaction's load timing
1634// info uses the first response, even if 1XX/informational.
1635void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561636 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381637 base::TimeDelta::FromMilliseconds(10);
1638
1639 HttpRequestInfo request;
1640 request.method = "GET";
1641 request.url = GURL("https://www.foo.com/");
1642 request.traffic_annotation =
1643 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1644
1645 SSLSocketDataProvider ssl(ASYNC, OK);
1646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1647
1648 std::vector<MockWrite> data_writes;
1649 std::vector<MockRead> data_reads;
1650
1651 spdy::SpdySerializedFrame spdy_req(
1652 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1653
Bence Béky4c325e52020-10-22 20:48:011654 spdy::Http2HeaderBlock spdy_resp1_headers;
Andrew Comminos1f2ff1cc2018-12-14 05:22:381655 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1656 spdy::SpdySerializedFrame spdy_resp1(
1657 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1658 spdy::SpdySerializedFrame spdy_resp2(
1659 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1660 spdy::SpdySerializedFrame spdy_data(
1661 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1662
1663 if (use_spdy) {
1664 ssl.next_proto = kProtoHTTP2;
1665
1666 data_writes = {CreateMockWrite(spdy_req, 0)};
1667
1668 data_reads = {
1669 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1670 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1671 MockRead(SYNCHRONOUS, OK, 5),
1672 };
1673 } else {
1674 data_writes = {
1675 MockWrite(ASYNC, 0,
1676 "GET / HTTP/1.1\r\n"
1677 "Host: www.foo.com\r\n"
1678 "Connection: keep-alive\r\n\r\n"),
1679 };
1680
1681 data_reads = {
1682 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1683 MockRead(ASYNC, ERR_IO_PENDING, 2),
1684
1685 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1686 MockRead(ASYNC, 4, "hello world"),
1687 MockRead(SYNCHRONOUS, OK, 5),
1688 };
1689 }
1690
1691 SequencedSocketData data(data_reads, data_writes);
1692 session_deps_.socket_factory->AddSocketDataProvider(&data);
1693
1694 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1695
1696 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1697
1698 TestCompletionCallback callback;
1699
1700 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1701 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1702
1703 data.RunUntilPaused();
1704 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1705 // the delay before parsing the 200 response.
1706 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561707 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381708 data.Resume();
1709
1710 rv = callback.WaitForResult();
1711 EXPECT_THAT(rv, IsOk());
1712
1713 const HttpResponseInfo* response = trans.GetResponseInfo();
1714 ASSERT_TRUE(response);
1715
1716 LoadTimingInfo load_timing_info;
1717 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1718 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1719 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561720 // Ensure we didn't include the delay in the TTFB time.
1721 EXPECT_EQ(load_timing_info.receive_headers_start,
1722 load_timing_info.connect_timing.connect_end);
1723 // Ensure that the mock clock advanced at all.
1724 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1725 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381726
1727 std::string response_data;
1728 rv = ReadTransaction(&trans, &response_data);
1729 EXPECT_THAT(rv, IsOk());
1730 EXPECT_EQ("hello world", response_data);
1731}
1732
Andrew Comminos517a92c2019-01-14 17:49:561733TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381734 Check100ResponseTiming(false /* use_spdy */);
1735}
1736
Andrew Comminos517a92c2019-01-14 17:49:561737TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381738 Check100ResponseTiming(true /* use_spdy */);
1739}
1740
bncd16676a2016-07-20 16:23:011741TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081742 HttpRequestInfo request;
1743 request.method = "POST";
1744 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101745 request.traffic_annotation =
1746 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081747
danakj1fd259a02016-04-16 03:17:091748 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161749 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081750
1751 MockRead data_reads[] = {
1752 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1753 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381754 };
Ryan Sleevib8d7ea02018-05-07 20:01:011755 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081756 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381757
zmo9528c9f42015-08-04 22:12:081758 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381759
tfarina42834112016-09-22 13:38:201760 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011761 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381762
zmo9528c9f42015-08-04 22:12:081763 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011764 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381765
zmo9528c9f42015-08-04 22:12:081766 std::string response_data;
bnc691fda62016-08-12 00:43:161767 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011768 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081769 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381770}
1771
bncd16676a2016-07-20 16:23:011772TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381773 HttpRequestInfo request;
1774 request.method = "POST";
1775 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101776 request.traffic_annotation =
1777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381778
danakj1fd259a02016-04-16 03:17:091779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161780 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271781
[email protected]ee9410e72010-01-07 01:42:381782 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061783 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381784 };
Ryan Sleevib8d7ea02018-05-07 20:01:011785 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071786 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381787
[email protected]49639fa2011-12-20 23:22:411788 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381789
tfarina42834112016-09-22 13:38:201790 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011791 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381792
1793 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011794 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381795}
1796
[email protected]23e482282013-06-14 16:08:021797void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511798 const MockWrite* write_failure,
1799 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421800 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521801 request.method = "GET";
1802 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101803 request.traffic_annotation =
1804 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521805
Matt Muellerd9342e3a2019-11-26 01:41:141806 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071807 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091808 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271809
[email protected]202965992011-12-07 23:04:511810 // Written data for successfully sending both requests.
1811 MockWrite data1_writes[] = {
1812 MockWrite("GET / HTTP/1.1\r\n"
1813 "Host: www.foo.com\r\n"
1814 "Connection: keep-alive\r\n\r\n"),
1815 MockWrite("GET / HTTP/1.1\r\n"
1816 "Host: www.foo.com\r\n"
1817 "Connection: keep-alive\r\n\r\n")
1818 };
1819
1820 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521821 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351822 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1823 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061824 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521825 };
[email protected]202965992011-12-07 23:04:511826
1827 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491828 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511829 data1_writes[1] = *write_failure;
1830 } else {
1831 ASSERT_TRUE(read_failure);
1832 data1_reads[2] = *read_failure;
1833 }
1834
Ryan Sleevib8d7ea02018-05-07 20:01:011835 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071836 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521837
1838 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351839 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1840 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061841 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521842 };
Ryan Sleevib8d7ea02018-05-07 20:01:011843 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071844 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521845
thestig9d3bb0c2015-01-24 00:49:511846 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521847 "hello", "world"
1848 };
1849
mikecironef22f9812016-10-04 03:40:191850 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521851 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411852 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521853
bnc691fda62016-08-12 00:43:161854 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521855
tfarina42834112016-09-22 13:38:201856 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521858
1859 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011860 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521861
[email protected]58e32bb2013-01-21 18:23:251862 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161863 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251864 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1865 if (i == 0) {
1866 first_socket_log_id = load_timing_info.socket_log_id;
1867 } else {
1868 // The second request should be using a new socket.
1869 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1870 }
1871
bnc691fda62016-08-12 00:43:161872 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521873 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521874
wezca1070932016-05-26 20:30:521875 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471876 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251877 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521878
1879 std::string response_data;
bnc691fda62016-08-12 00:43:161880 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011881 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251882 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521883 }
1884}
[email protected]3d2a59b2008-09-26 19:44:251885
[email protected]a34f61ee2014-03-18 20:59:491886void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1887 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101888 const MockRead* read_failure,
Yoichi Osatof17bc892020-08-05 01:49:041889 bool use_spdy,
1890 bool chunked_upload) {
1891 SpdyTestUtil spdy_util;
[email protected]a34f61ee2014-03-18 20:59:491892 HttpRequestInfo request;
1893 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101894 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101895 request.traffic_annotation =
1896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491897
Yoichi Osatof17bc892020-08-05 01:49:041898 const char upload_data[] = "foobar";
1899 ChunkedUploadDataStream upload_data_stream(0);
1900 if (chunked_upload) {
1901 request.method = "POST";
1902 upload_data_stream.AppendData(upload_data, base::size(upload_data) - 1,
1903 true);
1904 request.upload_data_stream = &upload_data_stream;
1905 }
1906
Matt Muellerd9342e3a2019-11-26 01:41:141907 RecordingTestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491908 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091909 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491910
[email protected]09356c652014-03-25 15:36:101911 SSLSocketDataProvider ssl1(ASYNC, OK);
1912 SSLSocketDataProvider ssl2(ASYNC, OK);
1913 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361914 ssl1.next_proto = kProtoHTTP2;
1915 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101916 }
1917 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1918 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491919
[email protected]09356c652014-03-25 15:36:101920 // SPDY versions of the request and response.
Yoichi Osatof17bc892020-08-05 01:49:041921
Bence Béky4c325e52020-10-22 20:48:011922 spdy::Http2HeaderBlock spdy_post_header_block;
Yoichi Osatof17bc892020-08-05 01:49:041923 spdy_post_header_block[spdy::kHttp2MethodHeader] = "POST";
1924 spdy_util.AddUrlToHeaderBlock(request.url.spec(), &spdy_post_header_block);
1925 spdy::SpdySerializedFrame spdy_request(
1926 chunked_upload
1927 ? spdy_util.ConstructSpdyHeaders(1, std::move(spdy_post_header_block),
1928 DEFAULT_PRIORITY, false)
1929 : spdy_util.ConstructSpdyGet(request.url.spec().c_str(), 1,
1930 DEFAULT_PRIORITY));
1931
1932 spdy::SpdySerializedFrame spdy_request_body(
1933 spdy_util.ConstructSpdyDataFrame(1, "foobar", true));
Ryan Hamilton0239aac2018-05-19 00:03:131934 spdy::SpdySerializedFrame spdy_response(
Yoichi Osatof17bc892020-08-05 01:49:041935 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131936 spdy::SpdySerializedFrame spdy_data(
Yoichi Osatof17bc892020-08-05 01:49:041937 spdy_util.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491938
[email protected]09356c652014-03-25 15:36:101939 // HTTP/1.1 versions of the request and response.
Yoichi Osatof17bc892020-08-05 01:49:041940 const std::string http_request =
1941 std::string(chunked_upload ? "POST" : "GET") +
1942 " / HTTP/1.1\r\n"
[email protected]09356c652014-03-25 15:36:101943 "Host: www.foo.com\r\n"
Yoichi Osatof17bc892020-08-05 01:49:041944 "Connection: keep-alive\r\n" +
1945 (chunked_upload ? "Transfer-Encoding: chunked\r\n\r\n" : "\r\n");
1946 const char* kHttpRequest = http_request.c_str();
[email protected]09356c652014-03-25 15:36:101947 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1948 const char kHttpData[] = "hello";
1949
1950 std::vector<MockRead> data1_reads;
1951 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491952 if (write_failure) {
1953 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101954 data1_writes.push_back(*write_failure);
1955 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491956 } else {
1957 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101958 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411959 data1_writes.push_back(CreateMockWrite(spdy_request));
Yoichi Osatof17bc892020-08-05 01:49:041960 if (chunked_upload)
1961 data1_writes.push_back(CreateMockWrite(spdy_request_body));
[email protected]09356c652014-03-25 15:36:101962 } else {
1963 data1_writes.push_back(MockWrite(kHttpRequest));
Yoichi Osatof17bc892020-08-05 01:49:041964 if (chunked_upload) {
1965 data1_writes.push_back(MockWrite("6\r\nfoobar\r\n"));
1966 data1_writes.push_back(MockWrite("0\r\n\r\n"));
1967 }
[email protected]09356c652014-03-25 15:36:101968 }
1969 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491970 }
1971
Ryan Sleevib8d7ea02018-05-07 20:01:011972 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491973 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1974
[email protected]09356c652014-03-25 15:36:101975 std::vector<MockRead> data2_reads;
1976 std::vector<MockWrite> data2_writes;
1977
1978 if (use_spdy) {
Yoichi Osatof17bc892020-08-05 01:49:041979 int seq = 0;
1980 data2_writes.push_back(CreateMockWrite(spdy_request, seq++, ASYNC));
1981 if (chunked_upload)
1982 data2_writes.push_back(CreateMockWrite(spdy_request_body, seq++, ASYNC));
1983 data2_reads.push_back(CreateMockRead(spdy_response, seq++, ASYNC));
1984 data2_reads.push_back(CreateMockRead(spdy_data, seq++, ASYNC));
1985 data2_reads.push_back(MockRead(ASYNC, OK, seq++));
[email protected]09356c652014-03-25 15:36:101986 } else {
Yoichi Osatof17bc892020-08-05 01:49:041987 int seq = 0;
[email protected]09356c652014-03-25 15:36:101988 data2_writes.push_back(
Yoichi Osatof17bc892020-08-05 01:49:041989 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), seq++));
1990 if (chunked_upload) {
1991 data2_writes.push_back(MockWrite(ASYNC, "6\r\nfoobar\r\n", 11, seq++));
1992 data2_writes.push_back(MockWrite(ASYNC, "0\r\n\r\n", 5, seq++));
1993 }
[email protected]09356c652014-03-25 15:36:101994 data2_reads.push_back(
Yoichi Osatof17bc892020-08-05 01:49:041995 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), seq++));
1996 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), seq++));
1997 data2_reads.push_back(MockRead(ASYNC, OK, seq++));
[email protected]09356c652014-03-25 15:36:101998 }
Ryan Sleevib8d7ea02018-05-07 20:01:011999 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:492000 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2001
2002 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:592003 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:492004 // Wait for the preconnect to complete.
2005 // TODO(davidben): Some way to wait for an idle socket count might be handy.
2006 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:232007 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:492008
2009 // Make the request.
2010 TestCompletionCallback callback;
2011
bnc691fda62016-08-12 00:43:162012 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:492013
tfarina42834112016-09-22 13:38:202014 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:492016
2017 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012018 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:492019
2020 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:162021 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:102022 TestLoadTimingNotReused(
2023 load_timing_info,
2024 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:492025
bnc691fda62016-08-12 00:43:162026 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522027 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:492028
wezca1070932016-05-26 20:30:522029 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:022030 if (response->was_fetched_via_spdy) {
2031 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2032 } else {
2033 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2034 }
[email protected]a34f61ee2014-03-18 20:59:492035
2036 std::string response_data;
bnc691fda62016-08-12 00:43:162037 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012038 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:102039 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:492040}
2041
Biljith Jayan45a41722017-08-16 18:43:142042// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:182043// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:142044// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
2045TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
2046 HttpRequestInfo request;
2047 request.method = "GET";
2048 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102049 request.traffic_annotation =
2050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:142051
2052 // Check whether we give up after the third try.
2053
2054 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:132055 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:142056 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:132057 spdy::SpdySerializedFrame spdy_response_go_away(
2058 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:012059 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2060 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:142061
2062 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:012063 StaticSocketDataProvider data1(data_read1, data_write);
2064 StaticSocketDataProvider data2(data_read1, data_write);
2065 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:142066
2067 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2068 AddSSLSocketData();
2069 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2070 AddSSLSocketData();
2071 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2072 AddSSLSocketData();
2073
2074 TestCompletionCallback callback;
2075 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2076 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2077
2078 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2080
2081 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:182082 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:142083}
2084
2085TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
2086 HttpRequestInfo request;
2087 request.method = "GET";
2088 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102089 request.traffic_annotation =
2090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:142091
2092 // Check whether we try atleast thrice before giving up.
2093
2094 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:132095 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:142096 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:132097 spdy::SpdySerializedFrame spdy_response_go_away(
2098 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:012099 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2100 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:142101
2102 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:132103 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:142104 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:132105 spdy::SpdySerializedFrame spdy_data(
2106 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:142107 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
2108 CreateMockRead(spdy_data, 2)};
2109
2110 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:012111 StaticSocketDataProvider data1(data_read1, data_write);
2112 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:142113 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:012114 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:142115
2116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2117 AddSSLSocketData();
2118 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2119 AddSSLSocketData();
2120 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2121 AddSSLSocketData();
2122
2123 TestCompletionCallback callback;
2124 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2125 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2126
2127 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2128 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2129
2130 rv = callback.WaitForResult();
2131 EXPECT_THAT(rv, IsOk());
2132}
2133
bncd16676a2016-07-20 16:23:012134TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:062135 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352136 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:512137}
2138
bncd16676a2016-07-20 16:23:012139TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:062140 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352141 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:252142}
2143
bncd16676a2016-07-20 16:23:012144TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:062145 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352146 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:252147}
2148
[email protected]d58ceea82014-06-04 10:55:542149// Make sure that on a 408 response (Request Timeout), the request is retried,
2150// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:012151TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:542152 MockRead read_failure(SYNCHRONOUS,
2153 "HTTP/1.1 408 Request Timeout\r\n"
2154 "Connection: Keep-Alive\r\n"
2155 "Content-Length: 6\r\n\r\n"
2156 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352157 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:542158}
2159
bncd16676a2016-07-20 16:23:012160TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:492161 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Yoichi Osatof17bc892020-08-05 01:49:042162 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2163 false /* use_spdy */);
2164 PreconnectErrorResendRequestTest(
2165 &write_failure, nullptr, false /* use_spdy */, true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492166}
2167
bncd16676a2016-07-20 16:23:012168TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:492169 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Yoichi Osatof17bc892020-08-05 01:49:042170 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2171 false /* use_spdy */);
2172 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2173 true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492174}
2175
bncd16676a2016-07-20 16:23:012176TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:492177 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042178 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2179 false /* use_spdy */);
2180 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2181 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102182}
2183
bncd16676a2016-07-20 16:23:012184TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102185 MockRead read_failure(ASYNC, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042186 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2187 false /* use_spdy */);
2188 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2189 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102190}
2191
[email protected]d58ceea82014-06-04 10:55:542192// Make sure that on a 408 response (Request Timeout), the request is retried,
2193// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012194TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542195 MockRead read_failure(SYNCHRONOUS,
2196 "HTTP/1.1 408 Request Timeout\r\n"
2197 "Connection: Keep-Alive\r\n"
2198 "Content-Length: 6\r\n\r\n"
2199 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352200 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
Yoichi Osatof17bc892020-08-05 01:49:042201 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2202 false /* use_spdy */);
2203 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2204 true /* chunked_upload */);
[email protected]d58ceea82014-06-04 10:55:542205}
2206
bncd16676a2016-07-20 16:23:012207TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102208 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Yoichi Osatof17bc892020-08-05 01:49:042209 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2210 true /* use_spdy */);
2211 PreconnectErrorResendRequestTest(&write_failure, nullptr, true /* use_spdy */,
2212 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102213}
2214
bncd16676a2016-07-20 16:23:012215TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102216 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Yoichi Osatof17bc892020-08-05 01:49:042217 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2218 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2219 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102220}
2221
bncd16676a2016-07-20 16:23:012222TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102223 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042224 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2225 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2226 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102227}
2228
bncd16676a2016-07-20 16:23:012229TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102230 MockRead read_failure(ASYNC, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042231 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2232 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2233 true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492234}
2235
bncd16676a2016-07-20 16:23:012236TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422237 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252238 request.method = "GET";
bncce36dca22015-04-21 22:11:232239 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102240 request.traffic_annotation =
2241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252242
danakj1fd259a02016-04-16 03:17:092243 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162244 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272245
[email protected]3d2a59b2008-09-26 19:44:252246 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062247 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352248 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2249 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062250 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252251 };
Ryan Sleevib8d7ea02018-05-07 20:01:012252 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072253 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252254
[email protected]49639fa2011-12-20 23:22:412255 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252256
tfarina42834112016-09-22 13:38:202257 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012258 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252259
2260 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012261 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592262
2263 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162264 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592265 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252266}
2267
2268// What do various browsers do when the server closes a non-keepalive
2269// connection without sending any response header or body?
2270//
2271// IE7: error page
2272// Safari 3.1.2 (Windows): error page
2273// Firefox 3.0.1: blank page
2274// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422275// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2276// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012277TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252278 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062279 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352280 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2281 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062282 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252283 };
Ryan Sleevib8d7ea02018-05-07 20:01:012284 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012285 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252286}
[email protected]1826a402014-01-08 15:40:482287
[email protected]7a5378b2012-11-04 03:25:172288// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2289// tests. There was a bug causing HttpNetworkTransaction to hang in the
2290// destructor in such situations.
2291// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012292TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172293 HttpRequestInfo request;
2294 request.method = "GET";
bncce36dca22015-04-21 22:11:232295 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102296 request.traffic_annotation =
2297 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172298
danakj1fd259a02016-04-16 03:17:092299 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582300 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192301 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172302
2303 MockRead data_reads[] = {
2304 MockRead("HTTP/1.0 200 OK\r\n"),
2305 MockRead("Connection: keep-alive\r\n"),
2306 MockRead("Content-Length: 100\r\n\r\n"),
2307 MockRead("hello"),
2308 MockRead(SYNCHRONOUS, 0),
2309 };
Ryan Sleevib8d7ea02018-05-07 20:01:012310 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072311 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172312
2313 TestCompletionCallback callback;
2314
tfarina42834112016-09-22 13:38:202315 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012316 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172317
2318 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012319 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172320
Victor Costan9c7302b2018-08-27 16:39:442321 scoped_refptr<IOBufferWithSize> io_buf =
2322 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502323 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172324 if (rv == ERR_IO_PENDING)
2325 rv = callback.WaitForResult();
2326 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502327 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012328 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172329
2330 trans.reset();
fdoray92e35a72016-06-10 15:54:552331 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172332 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2333}
2334
bncd16676a2016-07-20 16:23:012335TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172336 HttpRequestInfo request;
2337 request.method = "GET";
bncce36dca22015-04-21 22:11:232338 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102339 request.traffic_annotation =
2340 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172341
danakj1fd259a02016-04-16 03:17:092342 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582343 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192344 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172345
2346 MockRead data_reads[] = {
2347 MockRead("HTTP/1.0 200 OK\r\n"),
2348 MockRead("Connection: keep-alive\r\n"),
2349 MockRead("Content-Length: 100\r\n\r\n"),
2350 MockRead(SYNCHRONOUS, 0),
2351 };
Ryan Sleevib8d7ea02018-05-07 20:01:012352 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072353 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172354
2355 TestCompletionCallback callback;
2356
tfarina42834112016-09-22 13:38:202357 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172359
2360 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012361 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172362
Victor Costan9c7302b2018-08-27 16:39:442363 scoped_refptr<IOBufferWithSize> io_buf(
2364 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502365 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172366 if (rv == ERR_IO_PENDING)
2367 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012368 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172369
2370 trans.reset();
fdoray92e35a72016-06-10 15:54:552371 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172372 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2373}
2374
[email protected]0b0bf032010-09-21 18:08:502375// Test that we correctly reuse a keep-alive connection after not explicitly
2376// reading the body.
bncd16676a2016-07-20 16:23:012377TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132378 HttpRequestInfo request;
2379 request.method = "GET";
2380 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102381 request.traffic_annotation =
2382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132383
Matt Muellerd9342e3a2019-11-26 01:41:142384 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072385 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092386 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272387
mmenkecc2298e2015-12-07 18:20:182388 const char* request_data =
2389 "GET / HTTP/1.1\r\n"
2390 "Host: www.foo.com\r\n"
2391 "Connection: keep-alive\r\n\r\n";
2392 MockWrite data_writes[] = {
2393 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2394 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2395 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2396 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2397 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2398 };
2399
[email protected]0b0bf032010-09-21 18:08:502400 // Note that because all these reads happen in the same
2401 // StaticSocketDataProvider, it shows that the same socket is being reused for
2402 // all transactions.
mmenkecc2298e2015-12-07 18:20:182403 MockRead data_reads[] = {
2404 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2405 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2406 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2407 MockRead(ASYNC, 7,
2408 "HTTP/1.1 302 Found\r\n"
2409 "Content-Length: 0\r\n\r\n"),
2410 MockRead(ASYNC, 9,
2411 "HTTP/1.1 302 Found\r\n"
2412 "Content-Length: 5\r\n\r\n"
2413 "hello"),
2414 MockRead(ASYNC, 11,
2415 "HTTP/1.1 301 Moved Permanently\r\n"
2416 "Content-Length: 0\r\n\r\n"),
2417 MockRead(ASYNC, 13,
2418 "HTTP/1.1 301 Moved Permanently\r\n"
2419 "Content-Length: 5\r\n\r\n"
2420 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132421
mmenkecc2298e2015-12-07 18:20:182422 // In the next two rounds, IsConnectedAndIdle returns false, due to
2423 // the set_busy_before_sync_reads(true) call, while the
2424 // HttpNetworkTransaction is being shut down, but the socket is still
2425 // reuseable. See http://crbug.com/544255.
2426 MockRead(ASYNC, 15,
2427 "HTTP/1.1 200 Hunky-Dory\r\n"
2428 "Content-Length: 5\r\n\r\n"),
2429 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132430
mmenkecc2298e2015-12-07 18:20:182431 MockRead(ASYNC, 18,
2432 "HTTP/1.1 200 Hunky-Dory\r\n"
2433 "Content-Length: 5\r\n\r\n"
2434 "he"),
2435 MockRead(SYNCHRONOUS, 19, "llo"),
2436
2437 // The body of the final request is actually read.
2438 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2439 MockRead(ASYNC, 22, "hello"),
2440 };
Ryan Sleevib8d7ea02018-05-07 20:01:012441 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182442 data.set_busy_before_sync_reads(true);
2443 session_deps_.socket_factory->AddSocketDataProvider(&data);
2444
Avi Drissman4365a4782018-12-28 19:26:242445 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502446 std::string response_lines[kNumUnreadBodies];
2447
mikecironef22f9812016-10-04 03:40:192448 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182449 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412450 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132451
Jeremy Roman0579ed62017-08-29 15:56:192452 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582453 session.get());
[email protected]fc31d6a42010-06-24 18:05:132454
tfarina42834112016-09-22 13:38:202455 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012456 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132457
[email protected]58e32bb2013-01-21 18:23:252458 LoadTimingInfo load_timing_info;
2459 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2460 if (i == 0) {
2461 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2462 first_socket_log_id = load_timing_info.socket_log_id;
2463 } else {
2464 TestLoadTimingReused(load_timing_info);
2465 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2466 }
2467
[email protected]fc31d6a42010-06-24 18:05:132468 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182469 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132470
mmenkecc2298e2015-12-07 18:20:182471 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502472 response_lines[i] = response->headers->GetStatusLine();
2473
mmenkecc2298e2015-12-07 18:20:182474 // Delete the transaction without reading the response bodies. Then spin
2475 // the message loop, so the response bodies are drained.
2476 trans.reset();
2477 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132478 }
[email protected]0b0bf032010-09-21 18:08:502479
2480 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182481 "HTTP/1.1 204 No Content",
2482 "HTTP/1.1 205 Reset Content",
2483 "HTTP/1.1 304 Not Modified",
2484 "HTTP/1.1 302 Found",
2485 "HTTP/1.1 302 Found",
2486 "HTTP/1.1 301 Moved Permanently",
2487 "HTTP/1.1 301 Moved Permanently",
2488 "HTTP/1.1 200 Hunky-Dory",
2489 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502490 };
2491
Avi Drissman4365a4782018-12-28 19:26:242492 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272493 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502494
2495 for (int i = 0; i < kNumUnreadBodies; ++i)
2496 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2497
[email protected]49639fa2011-12-20 23:22:412498 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162499 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202500 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012501 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162502 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182503 ASSERT_TRUE(response);
2504 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502505 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2506 std::string response_data;
bnc691fda62016-08-12 00:43:162507 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012508 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502509 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132510}
2511
mmenke5f94fda2016-06-02 20:54:132512// Sockets that receive extra data after a response is complete should not be
2513// reused.
bncd16676a2016-07-20 16:23:012514TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2516 MockWrite data_writes1[] = {
2517 MockWrite("HEAD / HTTP/1.1\r\n"
2518 "Host: www.borked.com\r\n"
2519 "Connection: keep-alive\r\n\r\n"),
2520 };
2521
2522 MockRead data_reads1[] = {
2523 MockRead("HTTP/1.1 200 OK\r\n"
2524 "Connection: keep-alive\r\n"
2525 "Content-Length: 22\r\n\r\n"
2526 "This server is borked."),
2527 };
2528
2529 MockWrite data_writes2[] = {
2530 MockWrite("GET /foo HTTP/1.1\r\n"
2531 "Host: www.borked.com\r\n"
2532 "Connection: keep-alive\r\n\r\n"),
2533 };
2534
2535 MockRead data_reads2[] = {
2536 MockRead("HTTP/1.1 200 OK\r\n"
2537 "Content-Length: 3\r\n\r\n"
2538 "foo"),
2539 };
Ryan Sleevib8d7ea02018-05-07 20:01:012540 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132541 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012542 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132543 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2544
2545 TestCompletionCallback callback;
2546 HttpRequestInfo request1;
2547 request1.method = "HEAD";
2548 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102549 request1.traffic_annotation =
2550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132551
bnc87dcefc2017-05-25 12:47:582552 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192553 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202554 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012555 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132556
2557 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2558 ASSERT_TRUE(response1);
2559 ASSERT_TRUE(response1->headers);
2560 EXPECT_EQ(200, response1->headers->response_code());
2561 EXPECT_TRUE(response1->headers->IsKeepAlive());
2562
2563 std::string response_data1;
robpercival214763f2016-07-01 23:27:012564 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132565 EXPECT_EQ("", response_data1);
2566 // Deleting the transaction attempts to release the socket back into the
2567 // socket pool.
2568 trans1.reset();
2569
2570 HttpRequestInfo request2;
2571 request2.method = "GET";
2572 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102573 request2.traffic_annotation =
2574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132575
bnc87dcefc2017-05-25 12:47:582576 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192577 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202578 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012579 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132580
2581 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2582 ASSERT_TRUE(response2);
2583 ASSERT_TRUE(response2->headers);
2584 EXPECT_EQ(200, response2->headers->response_code());
2585
2586 std::string response_data2;
robpercival214763f2016-07-01 23:27:012587 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132588 EXPECT_EQ("foo", response_data2);
2589}
2590
bncd16676a2016-07-20 16:23:012591TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132592 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2593 MockWrite data_writes1[] = {
2594 MockWrite("GET / HTTP/1.1\r\n"
2595 "Host: www.borked.com\r\n"
2596 "Connection: keep-alive\r\n\r\n"),
2597 };
2598
2599 MockRead data_reads1[] = {
2600 MockRead("HTTP/1.1 200 OK\r\n"
2601 "Connection: keep-alive\r\n"
2602 "Content-Length: 22\r\n\r\n"
2603 "This server is borked."
2604 "Bonus data!"),
2605 };
2606
2607 MockWrite data_writes2[] = {
2608 MockWrite("GET /foo HTTP/1.1\r\n"
2609 "Host: www.borked.com\r\n"
2610 "Connection: keep-alive\r\n\r\n"),
2611 };
2612
2613 MockRead data_reads2[] = {
2614 MockRead("HTTP/1.1 200 OK\r\n"
2615 "Content-Length: 3\r\n\r\n"
2616 "foo"),
2617 };
Ryan Sleevib8d7ea02018-05-07 20:01:012618 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132619 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012620 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132621 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2622
2623 TestCompletionCallback callback;
2624 HttpRequestInfo request1;
2625 request1.method = "GET";
2626 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102627 request1.traffic_annotation =
2628 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132629
bnc87dcefc2017-05-25 12:47:582630 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192631 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202632 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012633 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132634
2635 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2636 ASSERT_TRUE(response1);
2637 ASSERT_TRUE(response1->headers);
2638 EXPECT_EQ(200, response1->headers->response_code());
2639 EXPECT_TRUE(response1->headers->IsKeepAlive());
2640
2641 std::string response_data1;
robpercival214763f2016-07-01 23:27:012642 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132643 EXPECT_EQ("This server is borked.", response_data1);
2644 // Deleting the transaction attempts to release the socket back into the
2645 // socket pool.
2646 trans1.reset();
2647
2648 HttpRequestInfo request2;
2649 request2.method = "GET";
2650 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102651 request2.traffic_annotation =
2652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132653
bnc87dcefc2017-05-25 12:47:582654 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192655 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202656 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012657 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132658
2659 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2660 ASSERT_TRUE(response2);
2661 ASSERT_TRUE(response2->headers);
2662 EXPECT_EQ(200, response2->headers->response_code());
2663
2664 std::string response_data2;
robpercival214763f2016-07-01 23:27:012665 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132666 EXPECT_EQ("foo", response_data2);
2667}
2668
bncd16676a2016-07-20 16:23:012669TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132670 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2671 MockWrite data_writes1[] = {
2672 MockWrite("GET / HTTP/1.1\r\n"
2673 "Host: www.borked.com\r\n"
2674 "Connection: keep-alive\r\n\r\n"),
2675 };
2676
2677 MockRead data_reads1[] = {
2678 MockRead("HTTP/1.1 200 OK\r\n"
2679 "Connection: keep-alive\r\n"
2680 "Transfer-Encoding: chunked\r\n\r\n"),
2681 MockRead("16\r\nThis server is borked.\r\n"),
2682 MockRead("0\r\n\r\nBonus data!"),
2683 };
2684
2685 MockWrite data_writes2[] = {
2686 MockWrite("GET /foo HTTP/1.1\r\n"
2687 "Host: www.borked.com\r\n"
2688 "Connection: keep-alive\r\n\r\n"),
2689 };
2690
2691 MockRead data_reads2[] = {
2692 MockRead("HTTP/1.1 200 OK\r\n"
2693 "Content-Length: 3\r\n\r\n"
2694 "foo"),
2695 };
Ryan Sleevib8d7ea02018-05-07 20:01:012696 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132697 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012698 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132699 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2700
2701 TestCompletionCallback callback;
2702 HttpRequestInfo request1;
2703 request1.method = "GET";
2704 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102705 request1.traffic_annotation =
2706 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132707
bnc87dcefc2017-05-25 12:47:582708 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192709 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202710 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012711 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132712
2713 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2714 ASSERT_TRUE(response1);
2715 ASSERT_TRUE(response1->headers);
2716 EXPECT_EQ(200, response1->headers->response_code());
2717 EXPECT_TRUE(response1->headers->IsKeepAlive());
2718
2719 std::string response_data1;
robpercival214763f2016-07-01 23:27:012720 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132721 EXPECT_EQ("This server is borked.", response_data1);
2722 // Deleting the transaction attempts to release the socket back into the
2723 // socket pool.
2724 trans1.reset();
2725
2726 HttpRequestInfo request2;
2727 request2.method = "GET";
2728 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102729 request2.traffic_annotation =
2730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132731
bnc87dcefc2017-05-25 12:47:582732 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192733 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202734 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012735 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132736
2737 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2738 ASSERT_TRUE(response2);
2739 ASSERT_TRUE(response2->headers);
2740 EXPECT_EQ(200, response2->headers->response_code());
2741
2742 std::string response_data2;
robpercival214763f2016-07-01 23:27:012743 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132744 EXPECT_EQ("foo", response_data2);
2745}
2746
2747// This is a little different from the others - it tests the case that the
2748// HttpStreamParser doesn't know if there's extra data on a socket or not when
2749// the HttpNetworkTransaction is torn down, because the response body hasn't
2750// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012751TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132752 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2753 MockWrite data_writes1[] = {
2754 MockWrite("GET / HTTP/1.1\r\n"
2755 "Host: www.borked.com\r\n"
2756 "Connection: keep-alive\r\n\r\n"),
2757 };
2758
2759 MockRead data_reads1[] = {
2760 MockRead("HTTP/1.1 200 OK\r\n"
2761 "Connection: keep-alive\r\n"
2762 "Transfer-Encoding: chunked\r\n\r\n"),
2763 MockRead("16\r\nThis server is borked.\r\n"),
2764 MockRead("0\r\n\r\nBonus data!"),
2765 };
Ryan Sleevib8d7ea02018-05-07 20:01:012766 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132767 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2768
2769 TestCompletionCallback callback;
2770 HttpRequestInfo request1;
2771 request1.method = "GET";
2772 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102773 request1.traffic_annotation =
2774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132775
bnc87dcefc2017-05-25 12:47:582776 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192777 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582778 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012779 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132780
bnc87dcefc2017-05-25 12:47:582781 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132782 ASSERT_TRUE(response1);
2783 ASSERT_TRUE(response1->headers);
2784 EXPECT_EQ(200, response1->headers->response_code());
2785 EXPECT_TRUE(response1->headers->IsKeepAlive());
2786
2787 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2788 // response body.
bnc87dcefc2017-05-25 12:47:582789 trans.reset();
mmenke5f94fda2016-06-02 20:54:132790
2791 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2792 // socket can't be reused, rather than returning it to the socket pool.
2793 base::RunLoop().RunUntilIdle();
2794
2795 // There should be no idle sockets in the pool.
2796 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2797}
2798
[email protected]038e9a32008-10-08 22:40:162799// Test the request-challenge-retry sequence for basic auth.
2800// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012801TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422802 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162803 request.method = "GET";
bncce36dca22015-04-21 22:11:232804 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102805 request.traffic_annotation =
2806 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162807
Matt Muellerd9342e3a2019-11-26 01:41:142808 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072809 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272812
[email protected]f9ee6b52008-11-08 06:46:232813 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232814 MockWrite(
2815 "GET / HTTP/1.1\r\n"
2816 "Host: www.example.org\r\n"
2817 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232818 };
2819
[email protected]038e9a32008-10-08 22:40:162820 MockRead data_reads1[] = {
2821 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2822 // Give a couple authenticate options (only the middle one is actually
2823 // supported).
[email protected]22927ad2009-09-21 19:56:192824 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162825 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2826 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2828 // Large content-length -- won't matter, as connection will be reset.
2829 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062830 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162831 };
2832
2833 // After calling trans->RestartWithAuth(), this is the request we should
2834 // be issuing -- the final header line contains the credentials.
2835 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232836 MockWrite(
2837 "GET / HTTP/1.1\r\n"
2838 "Host: www.example.org\r\n"
2839 "Connection: keep-alive\r\n"
2840 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162841 };
2842
2843 // Lastly, the server responds with the actual content.
2844 MockRead data_reads2[] = {
2845 MockRead("HTTP/1.0 200 OK\r\n"),
2846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2847 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062848 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162849 };
2850
Ryan Sleevib8d7ea02018-05-07 20:01:012851 StaticSocketDataProvider data1(data_reads1, data_writes1);
2852 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072853 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2854 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162855
[email protected]49639fa2011-12-20 23:22:412856 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162857
tfarina42834112016-09-22 13:38:202858 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012859 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162860
2861 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012862 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162863
[email protected]58e32bb2013-01-21 18:23:252864 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162865 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252866 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2867
Ryan Sleevib8d7ea02018-05-07 20:01:012868 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162869 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012870 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162871 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192872
bnc691fda62016-08-12 00:43:162873 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522874 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582875 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162876
[email protected]49639fa2011-12-20 23:22:412877 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162878
bnc691fda62016-08-12 00:43:162879 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162881
2882 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012883 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162884
[email protected]58e32bb2013-01-21 18:23:252885 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162886 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252887 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2888 // The load timing after restart should have a new socket ID, and times after
2889 // those of the first load timing.
2890 EXPECT_LE(load_timing_info1.receive_headers_end,
2891 load_timing_info2.connect_timing.connect_start);
2892 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2893
Ryan Sleevib8d7ea02018-05-07 20:01:012894 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162895 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012896 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162897 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192898
bnc691fda62016-08-12 00:43:162899 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522900 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582901 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162902 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162903}
2904
ttuttled9dbc652015-09-29 20:00:592905// Test the request-challenge-retry sequence for basic auth.
2906// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012907TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592908 HttpRequestInfo request;
2909 request.method = "GET";
2910 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102911 request.traffic_annotation =
2912 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592913
Matt Muellerd9342e3a2019-11-26 01:41:142914 RecordingTestNetLog log;
ttuttled9dbc652015-09-29 20:00:592915 MockHostResolver* resolver = new MockHostResolver();
2916 session_deps_.net_log = &log;
2917 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092918 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162919 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592920
2921 resolver->rules()->ClearRules();
2922 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2923
2924 MockWrite data_writes1[] = {
2925 MockWrite("GET / HTTP/1.1\r\n"
2926 "Host: www.example.org\r\n"
2927 "Connection: keep-alive\r\n\r\n"),
2928 };
2929
2930 MockRead data_reads1[] = {
2931 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2932 // Give a couple authenticate options (only the middle one is actually
2933 // supported).
2934 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2935 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2936 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2938 // Large content-length -- won't matter, as connection will be reset.
2939 MockRead("Content-Length: 10000\r\n\r\n"),
2940 MockRead(SYNCHRONOUS, ERR_FAILED),
2941 };
2942
2943 // After calling trans->RestartWithAuth(), this is the request we should
2944 // be issuing -- the final header line contains the credentials.
2945 MockWrite data_writes2[] = {
2946 MockWrite("GET / HTTP/1.1\r\n"
2947 "Host: www.example.org\r\n"
2948 "Connection: keep-alive\r\n"
2949 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2950 };
2951
2952 // Lastly, the server responds with the actual content.
2953 MockRead data_reads2[] = {
2954 MockRead("HTTP/1.0 200 OK\r\n"),
2955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2956 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2957 };
2958
Ryan Sleevib8d7ea02018-05-07 20:01:012959 StaticSocketDataProvider data1(data_reads1, data_writes1);
2960 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592961 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2962 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2963
2964 TestCompletionCallback callback1;
2965
bnc691fda62016-08-12 00:43:162966 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202967 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592968
2969 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162970 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592971 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2972
Ryan Sleevib8d7ea02018-05-07 20:01:012973 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162974 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012975 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162976 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592977
bnc691fda62016-08-12 00:43:162978 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592979 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582980 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592981
2982 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162983 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592984 ASSERT_FALSE(endpoint.address().empty());
2985 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2986
2987 resolver->rules()->ClearRules();
2988 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2989
2990 TestCompletionCallback callback2;
2991
bnc691fda62016-08-12 00:43:162992 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592993 AuthCredentials(kFoo, kBar), callback2.callback())));
2994
2995 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162996 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592997 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2998 // The load timing after restart should have a new socket ID, and times after
2999 // those of the first load timing.
3000 EXPECT_LE(load_timing_info1.receive_headers_end,
3001 load_timing_info2.connect_timing.connect_start);
3002 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3003
Ryan Sleevib8d7ea02018-05-07 20:01:013004 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:163005 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013006 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:163007 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:593008
bnc691fda62016-08-12 00:43:163009 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:593010 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583011 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:593012 EXPECT_EQ(100, response->headers->GetContentLength());
3013
bnc691fda62016-08-12 00:43:163014 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:593015 ASSERT_FALSE(endpoint.address().empty());
3016 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
3017}
3018
David Benjamin83ddfb32018-03-30 01:07:523019// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
3020// will eventually give up.
3021TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
3022 HttpRequestInfo request;
3023 request.method = "GET";
3024 request.url = GURL("http://www.example.org/");
3025 request.traffic_annotation =
3026 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3027
Matt Muellerd9342e3a2019-11-26 01:41:143028 RecordingTestNetLog log;
David Benjamin83ddfb32018-03-30 01:07:523029 session_deps_.net_log = &log;
3030 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3031 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3032
3033 MockWrite data_writes[] = {
3034 MockWrite("GET / HTTP/1.1\r\n"
3035 "Host: www.example.org\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3037 };
3038
3039 MockRead data_reads[] = {
3040 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3041 // Give a couple authenticate options (only the middle one is actually
3042 // supported).
3043 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
3044 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3045 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3047 // Large content-length -- won't matter, as connection will be reset.
3048 MockRead("Content-Length: 10000\r\n\r\n"),
3049 MockRead(SYNCHRONOUS, ERR_FAILED),
3050 };
3051
3052 // After calling trans->RestartWithAuth(), this is the request we should
3053 // be issuing -- the final header line contains the credentials.
3054 MockWrite data_writes_restart[] = {
3055 MockWrite("GET / HTTP/1.1\r\n"
3056 "Host: www.example.org\r\n"
3057 "Connection: keep-alive\r\n"
3058 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3059 };
3060
Ryan Sleevib8d7ea02018-05-07 20:01:013061 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:523062 session_deps_.socket_factory->AddSocketDataProvider(&data);
3063
3064 TestCompletionCallback callback;
3065 int rv = callback.GetResult(
3066 trans.Start(&request, callback.callback(), NetLogWithSource()));
3067
3068 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
3069 for (int i = 0; i < 32; i++) {
3070 // Check the previous response was a 401.
3071 EXPECT_THAT(rv, IsOk());
3072 const HttpResponseInfo* response = trans.GetResponseInfo();
3073 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583074 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:523075
3076 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:013077 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:523078 session_deps_.socket_factory->AddSocketDataProvider(
3079 data_restarts.back().get());
3080 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3081 callback.callback()));
3082 }
3083
3084 // After too many tries, the transaction should have given up.
3085 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
3086}
3087
bncd16676a2016-07-20 16:23:013088TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:463089 HttpRequestInfo request;
3090 request.method = "GET";
bncce36dca22015-04-21 22:11:233091 request.url = GURL("http://www.example.org/");
Matt Menke25eaa432020-08-25 00:10:003092 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103093 request.traffic_annotation =
3094 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:463095
danakj1fd259a02016-04-16 03:17:093096 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:163097 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:273098
[email protected]861fcd52009-08-26 02:33:463099 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:233100 MockWrite(
3101 "GET / HTTP/1.1\r\n"
3102 "Host: www.example.org\r\n"
3103 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:463104 };
3105
3106 MockRead data_reads[] = {
3107 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3108 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3109 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3110 // Large content-length -- won't matter, as connection will be reset.
3111 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063112 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:463113 };
3114
Ryan Sleevib8d7ea02018-05-07 20:01:013115 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073116 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:413117 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:463118
tfarina42834112016-09-22 13:38:203119 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:463121
3122 rv = callback.WaitForResult();
3123 EXPECT_EQ(0, rv);
3124
Ryan Sleevib8d7ea02018-05-07 20:01:013125 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163126 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013127 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163128 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:193129
bnc691fda62016-08-12 00:43:163130 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523131 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583132 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:463133}
3134
[email protected]2d2697f92009-02-18 21:00:323135// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3136// connection.
bncd16676a2016-07-20 16:23:013137TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:183138 // On the second pass, the body read of the auth challenge is synchronous, so
3139 // IsConnectedAndIdle returns false. The socket should still be drained and
3140 // reused. See http://crbug.com/544255.
3141 for (int i = 0; i < 2; ++i) {
3142 HttpRequestInfo request;
3143 request.method = "GET";
3144 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103145 request.traffic_annotation =
3146 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323147
Matt Muellerd9342e3a2019-11-26 01:41:143148 RecordingTestNetLog log;
mmenkecc2298e2015-12-07 18:20:183149 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:093150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273151
mmenkecc2298e2015-12-07 18:20:183152 MockWrite data_writes[] = {
3153 MockWrite(ASYNC, 0,
3154 "GET / HTTP/1.1\r\n"
3155 "Host: www.example.org\r\n"
3156 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323157
bnc691fda62016-08-12 00:43:163158 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:183159 // be issuing -- the final header line contains the credentials.
3160 MockWrite(ASYNC, 6,
3161 "GET / HTTP/1.1\r\n"
3162 "Host: www.example.org\r\n"
3163 "Connection: keep-alive\r\n"
3164 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3165 };
[email protected]2d2697f92009-02-18 21:00:323166
mmenkecc2298e2015-12-07 18:20:183167 MockRead data_reads[] = {
3168 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
3169 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3170 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3171 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
3172 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:323173
mmenkecc2298e2015-12-07 18:20:183174 // Lastly, the server responds with the actual content.
3175 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
3176 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3177 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
3178 MockRead(ASYNC, 10, "Hello"),
3179 };
[email protected]2d2697f92009-02-18 21:00:323180
Ryan Sleevib8d7ea02018-05-07 20:01:013181 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:183182 data.set_busy_before_sync_reads(true);
3183 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:463184
mmenkecc2298e2015-12-07 18:20:183185 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323186
bnc691fda62016-08-12 00:43:163187 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203188 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013189 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323190
mmenkecc2298e2015-12-07 18:20:183191 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:163192 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:183193 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:323194
bnc691fda62016-08-12 00:43:163195 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183196 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583197 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323198
mmenkecc2298e2015-12-07 18:20:183199 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:253200
bnc691fda62016-08-12 00:43:163201 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3202 callback2.callback());
robpercival214763f2016-07-01 23:27:013203 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323204
mmenkecc2298e2015-12-07 18:20:183205 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163206 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183207 TestLoadTimingReused(load_timing_info2);
3208 // The load timing after restart should have the same socket ID, and times
3209 // those of the first load timing.
3210 EXPECT_LE(load_timing_info1.receive_headers_end,
3211 load_timing_info2.send_start);
3212 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323213
bnc691fda62016-08-12 00:43:163214 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183215 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583216 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183217 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323218
mmenkecc2298e2015-12-07 18:20:183219 std::string response_data;
bnc691fda62016-08-12 00:43:163220 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323221
Ryan Sleevib8d7ea02018-05-07 20:01:013222 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163223 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013224 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163225 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183226 }
[email protected]2d2697f92009-02-18 21:00:323227}
3228
3229// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3230// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013231TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423232 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323233 request.method = "GET";
bncce36dca22015-04-21 22:11:233234 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103235 request.traffic_annotation =
3236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323237
danakj1fd259a02016-04-16 03:17:093238 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273239
[email protected]2d2697f92009-02-18 21:00:323240 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163241 MockWrite("GET / HTTP/1.1\r\n"
3242 "Host: www.example.org\r\n"
3243 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323244
bnc691fda62016-08-12 00:43:163245 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233246 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163247 MockWrite("GET / HTTP/1.1\r\n"
3248 "Host: www.example.org\r\n"
3249 "Connection: keep-alive\r\n"
3250 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323251 };
3252
[email protected]2d2697f92009-02-18 21:00:323253 MockRead data_reads1[] = {
3254 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3255 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313256 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323257
3258 // Lastly, the server responds with the actual content.
3259 MockRead("HTTP/1.1 200 OK\r\n"),
3260 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503261 MockRead("Content-Length: 5\r\n\r\n"),
3262 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323263 };
3264
[email protected]2d0a4f92011-05-05 16:38:463265 // An incorrect reconnect would cause this to be read.
3266 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063267 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463268 };
3269
Ryan Sleevib8d7ea02018-05-07 20:01:013270 StaticSocketDataProvider data1(data_reads1, data_writes1);
3271 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073272 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3273 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323274
[email protected]49639fa2011-12-20 23:22:413275 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323276
bnc691fda62016-08-12 00:43:163277 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203278 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013279 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323280
3281 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013282 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323283
bnc691fda62016-08-12 00:43:163284 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523285 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583286 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323287
[email protected]49639fa2011-12-20 23:22:413288 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323289
bnc691fda62016-08-12 00:43:163290 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323292
3293 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013294 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323295
bnc691fda62016-08-12 00:43:163296 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523297 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583298 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503299 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323300}
3301
3302// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3303// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013304TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423305 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323306 request.method = "GET";
bncce36dca22015-04-21 22:11:233307 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103308 request.traffic_annotation =
3309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323310
danakj1fd259a02016-04-16 03:17:093311 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273312
[email protected]2d2697f92009-02-18 21:00:323313 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163314 MockWrite("GET / HTTP/1.1\r\n"
3315 "Host: www.example.org\r\n"
3316 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323317
bnc691fda62016-08-12 00:43:163318 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233319 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163320 MockWrite("GET / HTTP/1.1\r\n"
3321 "Host: www.example.org\r\n"
3322 "Connection: keep-alive\r\n"
3323 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323324 };
3325
3326 // Respond with 5 kb of response body.
3327 std::string large_body_string("Unauthorized");
3328 large_body_string.append(5 * 1024, ' ');
3329 large_body_string.append("\r\n");
3330
3331 MockRead data_reads1[] = {
3332 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3333 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3335 // 5134 = 12 + 5 * 1024 + 2
3336 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063337 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323338
3339 // Lastly, the server responds with the actual content.
3340 MockRead("HTTP/1.1 200 OK\r\n"),
3341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503342 MockRead("Content-Length: 5\r\n\r\n"),
3343 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323344 };
3345
[email protected]2d0a4f92011-05-05 16:38:463346 // An incorrect reconnect would cause this to be read.
3347 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063348 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463349 };
3350
Ryan Sleevib8d7ea02018-05-07 20:01:013351 StaticSocketDataProvider data1(data_reads1, data_writes1);
3352 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073353 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3354 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323355
[email protected]49639fa2011-12-20 23:22:413356 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323357
bnc691fda62016-08-12 00:43:163358 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203359 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013360 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323361
3362 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013363 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323364
bnc691fda62016-08-12 00:43:163365 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523366 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583367 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323368
[email protected]49639fa2011-12-20 23:22:413369 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323370
bnc691fda62016-08-12 00:43:163371 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323373
3374 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013375 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323376
bnc691fda62016-08-12 00:43:163377 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523378 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583379 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503380 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323381}
3382
3383// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313384// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013385TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313386 HttpRequestInfo request;
3387 request.method = "GET";
bncce36dca22015-04-21 22:11:233388 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103389 request.traffic_annotation =
3390 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313391
danakj1fd259a02016-04-16 03:17:093392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273393
[email protected]11203f012009-11-12 23:02:313394 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233395 MockWrite(
3396 "GET / HTTP/1.1\r\n"
3397 "Host: www.example.org\r\n"
3398 "Connection: keep-alive\r\n\r\n"),
3399 // This simulates the seemingly successful write to a closed connection
3400 // if the bug is not fixed.
3401 MockWrite(
3402 "GET / HTTP/1.1\r\n"
3403 "Host: www.example.org\r\n"
3404 "Connection: keep-alive\r\n"
3405 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313406 };
3407
3408 MockRead data_reads1[] = {
3409 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3410 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3412 MockRead("Content-Length: 14\r\n\r\n"),
3413 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063414 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313415 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063416 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313417 };
3418
bnc691fda62016-08-12 00:43:163419 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313420 // be issuing -- the final header line contains the credentials.
3421 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233422 MockWrite(
3423 "GET / HTTP/1.1\r\n"
3424 "Host: www.example.org\r\n"
3425 "Connection: keep-alive\r\n"
3426 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313427 };
3428
3429 // Lastly, the server responds with the actual content.
3430 MockRead data_reads2[] = {
3431 MockRead("HTTP/1.1 200 OK\r\n"),
3432 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503433 MockRead("Content-Length: 5\r\n\r\n"),
3434 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313435 };
3436
Ryan Sleevib8d7ea02018-05-07 20:01:013437 StaticSocketDataProvider data1(data_reads1, data_writes1);
3438 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073439 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3440 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313441
[email protected]49639fa2011-12-20 23:22:413442 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313443
bnc691fda62016-08-12 00:43:163444 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203445 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013446 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313447
3448 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013449 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313450
bnc691fda62016-08-12 00:43:163451 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523452 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583453 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313454
[email protected]49639fa2011-12-20 23:22:413455 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313456
bnc691fda62016-08-12 00:43:163457 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013458 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313459
3460 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013461 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313462
bnc691fda62016-08-12 00:43:163463 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523464 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583465 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503466 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313467}
3468
[email protected]394816e92010-08-03 07:38:593469// Test the request-challenge-retry sequence for basic auth, over a connection
3470// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013471TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013472 HttpRequestInfo request;
3473 request.method = "GET";
bncce36dca22015-04-21 22:11:233474 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013475 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003476 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103477 request.traffic_annotation =
3478 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013479
3480 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593481 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563482 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493483 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143484 RecordingBoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013485 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093486 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013487
3488 // Since we have proxy, should try to establish tunnel.
3489 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543490 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173491 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543492 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013493 };
3494
mmenkee71e15332015-10-07 16:39:543495 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013496 // connection.
3497 MockRead data_reads1[] = {
3498 // No credentials.
3499 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3500 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543501 };
ttuttle34f63b52015-03-05 04:33:013502
mmenkee71e15332015-10-07 16:39:543503 // Since the first connection couldn't be reused, need to establish another
3504 // once given credentials.
3505 MockWrite data_writes2[] = {
3506 // After calling trans->RestartWithAuth(), this is the request we should
3507 // be issuing -- the final header line contains the credentials.
3508 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173509 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543510 "Proxy-Connection: keep-alive\r\n"
3511 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3512
3513 MockWrite("GET / HTTP/1.1\r\n"
3514 "Host: www.example.org\r\n"
3515 "Connection: keep-alive\r\n\r\n"),
3516 };
3517
3518 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013519 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3520
3521 MockRead("HTTP/1.1 200 OK\r\n"),
3522 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3523 MockRead("Content-Length: 5\r\n\r\n"),
3524 MockRead(SYNCHRONOUS, "hello"),
3525 };
3526
Ryan Sleevib8d7ea02018-05-07 20:01:013527 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013528 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013529 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543530 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013531 SSLSocketDataProvider ssl(ASYNC, OK);
3532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3533
3534 TestCompletionCallback callback1;
Titouan Rigoudyba507a882020-07-31 12:15:153535 ConnectedHandler connected_handler;
ttuttle34f63b52015-03-05 04:33:013536
bnc87dcefc2017-05-25 12:47:583537 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193538 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013539
Titouan Rigoudyba507a882020-07-31 12:15:153540 trans->SetConnectedCallback(connected_handler.Callback());
3541
ttuttle34f63b52015-03-05 04:33:013542 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013544
3545 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013546 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543547 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013548 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003549 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3550 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013551 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003552 entries, pos,
3553 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3554 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013555
Titouan Rigoudyba507a882020-07-31 12:15:153556 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3557 // authentication is required. We should notify the callback that a connection
3558 // was established, even though the stream might not be ready for us to send
3559 // data through it.
3560 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3561
ttuttle34f63b52015-03-05 04:33:013562 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523563 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013564 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523565 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013566 EXPECT_EQ(407, response->headers->response_code());
3567 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583568 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013569
3570 LoadTimingInfo load_timing_info;
3571 // CONNECT requests and responses are handled at the connect job level, so
3572 // the transaction does not yet have a connection.
3573 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3574
3575 TestCompletionCallback callback2;
3576
3577 rv =
3578 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013579 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013580
3581 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013582 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013583
3584 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523585 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013586
3587 EXPECT_TRUE(response->headers->IsKeepAlive());
3588 EXPECT_EQ(200, response->headers->response_code());
3589 EXPECT_EQ(5, response->headers->GetContentLength());
3590 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3591
Titouan Rigoudyba507a882020-07-31 12:15:153592 TransportInfo expected_transport;
3593 expected_transport.type = TransportType::kProxied;
3594 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3595 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3596
Matt Menke96092e62019-10-18 04:09:333597 // Check that credentials were successfully cached, with the right target.
3598 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3599 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263600 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333601 ASSERT_TRUE(entry);
3602 ASSERT_EQ(kFoo, entry->credentials().username());
3603 ASSERT_EQ(kBar, entry->credentials().password());
3604
ttuttle34f63b52015-03-05 04:33:013605 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583606 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013607
3608 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3609 TestLoadTimingNotReusedWithPac(load_timing_info,
3610 CONNECT_TIMING_HAS_SSL_TIMES);
3611
3612 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113613 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle34f63b52015-03-05 04:33:013614}
3615
3616// Test the request-challenge-retry sequence for basic auth, over a connection
3617// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013618TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593619 HttpRequestInfo request;
3620 request.method = "GET";
bncce36dca22015-04-21 22:11:233621 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593622 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003623 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103624 request.traffic_annotation =
3625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593626
[email protected]cb9bf6ca2011-01-28 13:15:273627 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593628 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563629 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493630 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143631 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073632 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093633 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273634
[email protected]394816e92010-08-03 07:38:593635 // Since we have proxy, should try to establish tunnel.
3636 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543637 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173638 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543639 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113640 };
3641
mmenkee71e15332015-10-07 16:39:543642 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083643 // connection.
3644 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543645 // No credentials.
3646 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3647 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3648 MockRead("Proxy-Connection: close\r\n\r\n"),
3649 };
mmenkee0b5c882015-08-26 20:29:113650
mmenkee71e15332015-10-07 16:39:543651 MockWrite data_writes2[] = {
3652 // After calling trans->RestartWithAuth(), this is the request we should
3653 // be issuing -- the final header line contains the credentials.
3654 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173655 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543656 "Proxy-Connection: keep-alive\r\n"
3657 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083658
mmenkee71e15332015-10-07 16:39:543659 MockWrite("GET / HTTP/1.1\r\n"
3660 "Host: www.example.org\r\n"
3661 "Connection: keep-alive\r\n\r\n"),
3662 };
3663
3664 MockRead data_reads2[] = {
3665 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3666
3667 MockRead("HTTP/1.1 200 OK\r\n"),
3668 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3669 MockRead("Content-Length: 5\r\n\r\n"),
3670 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593671 };
3672
Ryan Sleevib8d7ea02018-05-07 20:01:013673 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073674 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013675 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543676 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063677 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073678 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593679
Titouan Rigoudyba507a882020-07-31 12:15:153680 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:413681 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593682
bnc87dcefc2017-05-25 12:47:583683 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193684 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503685
Titouan Rigoudyba507a882020-07-31 12:15:153686 trans->SetConnectedCallback(connected_handler.Callback());
3687
[email protected]49639fa2011-12-20 23:22:413688 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013689 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593690
3691 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013692 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543693 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593694 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003695 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3696 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593697 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403698 entries, pos,
mikecirone8b85c432016-09-08 19:11:003699 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3700 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593701
3702 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523703 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013704 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523705 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593706 EXPECT_EQ(407, response->headers->response_code());
3707 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583708 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593709
Titouan Rigoudyba507a882020-07-31 12:15:153710 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3711 // authentication is required. We should notify the callback that a connection
3712 // was established, even though the stream might not be ready for us to send
3713 // data through it.
3714 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3715
[email protected]029c83b62013-01-24 05:28:203716 LoadTimingInfo load_timing_info;
3717 // CONNECT requests and responses are handled at the connect job level, so
3718 // the transaction does not yet have a connection.
3719 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3720
[email protected]49639fa2011-12-20 23:22:413721 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593722
[email protected]49639fa2011-12-20 23:22:413723 rv = trans->RestartWithAuth(
3724 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593726
3727 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013728 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593729
3730 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523731 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593732
3733 EXPECT_TRUE(response->headers->IsKeepAlive());
3734 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503735 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593736 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3737
Titouan Rigoudyba507a882020-07-31 12:15:153738 TransportInfo expected_transport;
3739 expected_transport.type = TransportType::kProxied;
3740 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3741 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3742
[email protected]394816e92010-08-03 07:38:593743 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583744 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503745
[email protected]029c83b62013-01-24 05:28:203746 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3747 TestLoadTimingNotReusedWithPac(load_timing_info,
3748 CONNECT_TIMING_HAS_SSL_TIMES);
3749
[email protected]0b0bf032010-09-21 18:08:503750 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113751 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]394816e92010-08-03 07:38:593752}
3753
[email protected]11203f012009-11-12 23:02:313754// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013755// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013756TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233757 // On the second pass, the body read of the auth challenge is synchronous, so
3758 // IsConnectedAndIdle returns false. The socket should still be drained and
3759 // reused. See http://crbug.com/544255.
3760 for (int i = 0; i < 2; ++i) {
3761 HttpRequestInfo request;
3762 request.method = "GET";
3763 request.url = GURL("https://www.example.org/");
3764 // Ensure that proxy authentication is attempted even
3765 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003766 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103767 request.traffic_annotation =
3768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013769
mmenked39192ee2015-12-09 00:57:233770 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593771 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563772 ConfiguredProxyResolutionService::CreateFixed(
3773 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143774 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233775 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093776 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013777
bnc691fda62016-08-12 00:43:163778 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013779
mmenked39192ee2015-12-09 00:57:233780 // Since we have proxy, should try to establish tunnel.
3781 MockWrite data_writes1[] = {
3782 MockWrite(ASYNC, 0,
3783 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3784 "Host: www.example.org:443\r\n"
3785 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013786
bnc691fda62016-08-12 00:43:163787 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233788 // be issuing -- the final header line contains the credentials.
3789 MockWrite(ASYNC, 3,
3790 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3791 "Host: www.example.org:443\r\n"
3792 "Proxy-Connection: keep-alive\r\n"
3793 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3794 };
ttuttle34f63b52015-03-05 04:33:013795
mmenked39192ee2015-12-09 00:57:233796 // The proxy responds to the connect with a 407, using a persistent
3797 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3798 MockRead data_reads1[] = {
3799 // No credentials.
3800 MockRead(ASYNC, 1,
3801 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3802 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3803 "Proxy-Connection: keep-alive\r\n"
3804 "Content-Length: 10\r\n\r\n"),
3805 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013806
mmenked39192ee2015-12-09 00:57:233807 // Wrong credentials (wrong password).
3808 MockRead(ASYNC, 4,
3809 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3810 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3811 "Proxy-Connection: keep-alive\r\n"
3812 "Content-Length: 10\r\n\r\n"),
3813 // No response body because the test stops reading here.
3814 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3815 };
ttuttle34f63b52015-03-05 04:33:013816
Ryan Sleevib8d7ea02018-05-07 20:01:013817 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233818 data1.set_busy_before_sync_reads(true);
3819 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013820
mmenked39192ee2015-12-09 00:57:233821 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013822
bnc691fda62016-08-12 00:43:163823 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013824 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013825
Eric Roman79cc7552019-07-19 02:17:543826 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233827 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003828 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3829 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233830 ExpectLogContainsSomewhere(
3831 entries, pos,
mikecirone8b85c432016-09-08 19:11:003832 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3833 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013834
bnc691fda62016-08-12 00:43:163835 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233836 ASSERT_TRUE(response);
3837 ASSERT_TRUE(response->headers);
3838 EXPECT_TRUE(response->headers->IsKeepAlive());
3839 EXPECT_EQ(407, response->headers->response_code());
3840 EXPECT_EQ(10, response->headers->GetContentLength());
3841 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583842 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013843
mmenked39192ee2015-12-09 00:57:233844 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013845
mmenked39192ee2015-12-09 00:57:233846 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163847 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3848 callback2.callback());
robpercival214763f2016-07-01 23:27:013849 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013850
bnc691fda62016-08-12 00:43:163851 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233852 ASSERT_TRUE(response);
3853 ASSERT_TRUE(response->headers);
3854 EXPECT_TRUE(response->headers->IsKeepAlive());
3855 EXPECT_EQ(407, response->headers->response_code());
3856 EXPECT_EQ(10, response->headers->GetContentLength());
3857 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583858 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013859
mmenked39192ee2015-12-09 00:57:233860 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3861 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113862 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233863 }
ttuttle34f63b52015-03-05 04:33:013864}
3865
3866// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3867// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013868TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233869 // On the second pass, the body read of the auth challenge is synchronous, so
3870 // IsConnectedAndIdle returns false. The socket should still be drained and
3871 // reused. See http://crbug.com/544255.
3872 for (int i = 0; i < 2; ++i) {
3873 HttpRequestInfo request;
3874 request.method = "GET";
3875 request.url = GURL("https://www.example.org/");
3876 // Ensure that proxy authentication is attempted even
3877 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003878 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103879 request.traffic_annotation =
3880 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233881
3882 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593883 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563884 ConfiguredProxyResolutionService::CreateFixed(
3885 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143886 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233887 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093888 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233889
bnc691fda62016-08-12 00:43:163890 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233891
3892 // Since we have proxy, should try to establish tunnel.
3893 MockWrite data_writes1[] = {
3894 MockWrite(ASYNC, 0,
3895 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3896 "Host: www.example.org:443\r\n"
3897 "Proxy-Connection: keep-alive\r\n\r\n"),
3898
bnc691fda62016-08-12 00:43:163899 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233900 // be issuing -- the final header line contains the credentials.
3901 MockWrite(ASYNC, 3,
3902 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3903 "Host: www.example.org:443\r\n"
3904 "Proxy-Connection: keep-alive\r\n"
3905 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3906 };
3907
3908 // The proxy responds to the connect with a 407, using a persistent
3909 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3910 MockRead data_reads1[] = {
3911 // No credentials.
3912 MockRead(ASYNC, 1,
3913 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3914 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3915 "Content-Length: 10\r\n\r\n"),
3916 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3917
3918 // Wrong credentials (wrong password).
3919 MockRead(ASYNC, 4,
3920 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3921 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3922 "Content-Length: 10\r\n\r\n"),
3923 // No response body because the test stops reading here.
3924 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3925 };
3926
Ryan Sleevib8d7ea02018-05-07 20:01:013927 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233928 data1.set_busy_before_sync_reads(true);
3929 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3930
3931 TestCompletionCallback callback1;
3932
bnc691fda62016-08-12 00:43:163933 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013934 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233935
Eric Roman79cc7552019-07-19 02:17:543936 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233937 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003938 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3939 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233940 ExpectLogContainsSomewhere(
3941 entries, pos,
mikecirone8b85c432016-09-08 19:11:003942 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3943 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233944
bnc691fda62016-08-12 00:43:163945 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233946 ASSERT_TRUE(response);
3947 ASSERT_TRUE(response->headers);
3948 EXPECT_TRUE(response->headers->IsKeepAlive());
3949 EXPECT_EQ(407, response->headers->response_code());
3950 EXPECT_EQ(10, response->headers->GetContentLength());
3951 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583952 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503953 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233954
3955 TestCompletionCallback callback2;
3956
3957 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163958 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3959 callback2.callback());
robpercival214763f2016-07-01 23:27:013960 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233961
bnc691fda62016-08-12 00:43:163962 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233963 ASSERT_TRUE(response);
3964 ASSERT_TRUE(response->headers);
3965 EXPECT_TRUE(response->headers->IsKeepAlive());
3966 EXPECT_EQ(407, response->headers->response_code());
3967 EXPECT_EQ(10, response->headers->GetContentLength());
3968 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583969 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503970 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233971
3972 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3973 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113974 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233975 }
3976}
3977
3978// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3979// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3980// the case the server sends extra data on the original socket, so it can't be
3981// reused.
bncd16676a2016-07-20 16:23:013982TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273983 HttpRequestInfo request;
3984 request.method = "GET";
bncce36dca22015-04-21 22:11:233985 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273986 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003987 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:103988 request.traffic_annotation =
3989 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273990
[email protected]2d2697f92009-02-18 21:00:323991 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593992 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563993 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493994 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143995 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073996 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093997 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323998
[email protected]2d2697f92009-02-18 21:00:323999 // Since we have proxy, should try to establish tunnel.
4000 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:234001 MockWrite(ASYNC, 0,
4002 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174003 "Host: www.example.org:443\r\n"
4004 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234005 };
[email protected]2d2697f92009-02-18 21:00:324006
mmenked39192ee2015-12-09 00:57:234007 // The proxy responds to the connect with a 407, using a persistent, but sends
4008 // extra data, so the socket cannot be reused.
4009 MockRead data_reads1[] = {
4010 // No credentials.
4011 MockRead(ASYNC, 1,
4012 "HTTP/1.1 407 Proxy Authentication Required\r\n"
4013 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4014 "Content-Length: 10\r\n\r\n"),
4015 MockRead(SYNCHRONOUS, 2, "0123456789"),
4016 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
4017 };
4018
4019 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:234020 // After calling trans->RestartWithAuth(), this is the request we should
4021 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:234022 MockWrite(ASYNC, 0,
4023 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174024 "Host: www.example.org:443\r\n"
4025 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:234026 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4027
4028 MockWrite(ASYNC, 2,
4029 "GET / HTTP/1.1\r\n"
4030 "Host: www.example.org\r\n"
4031 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:324032 };
4033
mmenked39192ee2015-12-09 00:57:234034 MockRead data_reads2[] = {
4035 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:324036
mmenked39192ee2015-12-09 00:57:234037 MockRead(ASYNC, 3,
4038 "HTTP/1.1 200 OK\r\n"
4039 "Content-Type: text/html; charset=iso-8859-1\r\n"
4040 "Content-Length: 5\r\n\r\n"),
4041 // No response body because the test stops reading here.
4042 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:324043 };
4044
Ryan Sleevib8d7ea02018-05-07 20:01:014045 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:234046 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:074047 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014048 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:234049 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4050 SSLSocketDataProvider ssl(ASYNC, OK);
4051 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:324052
[email protected]49639fa2011-12-20 23:22:414053 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:324054
bnc87dcefc2017-05-25 12:47:584055 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194056 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:324057
mmenked39192ee2015-12-09 00:57:234058 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014059 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:234060
Eric Roman79cc7552019-07-19 02:17:544061 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:394062 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004063 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4064 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:394065 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404066 entries, pos,
mikecirone8b85c432016-09-08 19:11:004067 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4068 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:324069
[email protected]1c773ea12009-04-28 19:58:424070 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244071 ASSERT_TRUE(response);
4072 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:324073 EXPECT_TRUE(response->headers->IsKeepAlive());
4074 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424075 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:584076 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:324077
mmenked39192ee2015-12-09 00:57:234078 LoadTimingInfo load_timing_info;
4079 // CONNECT requests and responses are handled at the connect job level, so
4080 // the transaction does not yet have a connection.
4081 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4082
[email protected]49639fa2011-12-20 23:22:414083 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:324084
mmenked39192ee2015-12-09 00:57:234085 rv =
4086 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:014087 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:324088
[email protected]2d2697f92009-02-18 21:00:324089 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:234090 EXPECT_EQ(200, response->headers->response_code());
4091 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:424092 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:134093
mmenked39192ee2015-12-09 00:57:234094 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584095 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:234096
4097 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4098 TestLoadTimingNotReusedWithPac(load_timing_info,
4099 CONNECT_TIMING_HAS_SSL_TIMES);
4100
4101 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114102 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]2d2697f92009-02-18 21:00:324103}
4104
mmenkee71e15332015-10-07 16:39:544105// Test the case a proxy closes a socket while the challenge body is being
4106// drained.
bncd16676a2016-07-20 16:23:014107TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:544108 HttpRequestInfo request;
4109 request.method = "GET";
4110 request.url = GURL("https://www.example.org/");
4111 // Ensure that proxy authentication is attempted even
4112 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:004113 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:104114 request.traffic_annotation =
4115 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:544116
4117 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564118 session_deps_.proxy_resolution_service =
4119 ConfiguredProxyResolutionService::CreateFixed(
4120 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:094121 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:544122
bnc691fda62016-08-12 00:43:164123 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:544124
4125 // Since we have proxy, should try to establish tunnel.
4126 MockWrite data_writes1[] = {
4127 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174128 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:544129 "Proxy-Connection: keep-alive\r\n\r\n"),
4130 };
4131
4132 // The proxy responds to the connect with a 407, using a persistent
4133 // connection.
4134 MockRead data_reads1[] = {
4135 // No credentials.
4136 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4137 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4138 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
4139 // Server hands up in the middle of the body.
4140 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
4141 };
4142
4143 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:164144 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:544145 // be issuing -- the final header line contains the credentials.
4146 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174147 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:544148 "Proxy-Connection: keep-alive\r\n"
4149 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4150
4151 MockWrite("GET / HTTP/1.1\r\n"
4152 "Host: www.example.org\r\n"
4153 "Connection: keep-alive\r\n\r\n"),
4154 };
4155
4156 MockRead data_reads2[] = {
4157 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4158
4159 MockRead("HTTP/1.1 200 OK\r\n"),
4160 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4161 MockRead("Content-Length: 5\r\n\r\n"),
4162 MockRead(SYNCHRONOUS, "hello"),
4163 };
4164
Ryan Sleevib8d7ea02018-05-07 20:01:014165 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:544166 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014167 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:544168 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4169 SSLSocketDataProvider ssl(ASYNC, OK);
4170 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4171
4172 TestCompletionCallback callback;
4173
tfarina42834112016-09-22 13:38:204174 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014175 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:544176
bnc691fda62016-08-12 00:43:164177 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:544178 ASSERT_TRUE(response);
4179 ASSERT_TRUE(response->headers);
4180 EXPECT_TRUE(response->headers->IsKeepAlive());
4181 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:584182 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:544183
bnc691fda62016-08-12 00:43:164184 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:014185 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:544186
bnc691fda62016-08-12 00:43:164187 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:544188 ASSERT_TRUE(response);
4189 ASSERT_TRUE(response->headers);
4190 EXPECT_TRUE(response->headers->IsKeepAlive());
4191 EXPECT_EQ(200, response->headers->response_code());
4192 std::string body;
bnc691fda62016-08-12 00:43:164193 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:544194 EXPECT_EQ("hello", body);
4195}
4196
[email protected]a8e9b162009-03-12 00:06:444197// Test that we don't read the response body when we fail to establish a tunnel,
4198// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:014199TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:274200 HttpRequestInfo request;
4201 request.method = "GET";
bncce36dca22015-04-21 22:11:234202 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104203 request.traffic_annotation =
4204 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274205
[email protected]a8e9b162009-03-12 00:06:444206 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564207 session_deps_.proxy_resolution_service =
4208 ConfiguredProxyResolutionService::CreateFixed(
4209 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:444210
danakj1fd259a02016-04-16 03:17:094211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:444212
bnc691fda62016-08-12 00:43:164213 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:444214
[email protected]a8e9b162009-03-12 00:06:444215 // Since we have proxy, should try to establish tunnel.
4216 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174217 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4218 "Host: www.example.org:443\r\n"
4219 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:444220 };
4221
4222 // The proxy responds to the connect with a 407.
4223 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:244224 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4225 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4226 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234227 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:244228 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:444229 };
4230
Ryan Sleevib8d7ea02018-05-07 20:01:014231 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074232 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444233
[email protected]49639fa2011-12-20 23:22:414234 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444235
tfarina42834112016-09-22 13:38:204236 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014237 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444238
4239 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014240 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444241
bnc691fda62016-08-12 00:43:164242 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244243 ASSERT_TRUE(response);
4244 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444245 EXPECT_TRUE(response->headers->IsKeepAlive());
4246 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424247 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444248
4249 std::string response_data;
bnc691fda62016-08-12 00:43:164250 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014251 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184252
4253 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114254 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]a8e9b162009-03-12 00:06:444255}
4256
Matt Menke96092e62019-10-18 04:09:334257// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4258// are the same, but the user/passwords are different. Serves to verify
4259// credentials are correctly separated based on HttpAuth::Target.
4260TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
4261 HttpRequestInfo request;
4262 request.method = "GET";
4263 request.url = GURL("http://myproxy:70/");
4264 request.traffic_annotation =
4265 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4266
4267 // Proxy matches request URL.
4268 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564269 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke96092e62019-10-18 04:09:334270 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144271 RecordingBoundTestNetLog log;
Matt Menke96092e62019-10-18 04:09:334272 session_deps_.net_log = log.bound().net_log();
4273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4274
4275 MockWrite data_writes[] = {
4276 // Initial request gets a proxy auth challenge.
4277 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4278 "Host: myproxy:70\r\n"
4279 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264280 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334281 // challenge.
4282 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4283 "Host: myproxy:70\r\n"
4284 "Proxy-Connection: keep-alive\r\n"
4285 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264286 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334287 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4288 "Host: myproxy:70\r\n"
4289 "Proxy-Connection: keep-alive\r\n"
4290 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4291 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4292 // A second request should preemptively send the correct proxy and server
4293 // auth headers.
4294 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4295 "Host: myproxy:70\r\n"
4296 "Proxy-Connection: keep-alive\r\n"
4297 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4298 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4299 };
4300
4301 MockRead data_reads[] = {
4302 // Proxy auth challenge.
4303 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4304 "Proxy-Connection: keep-alive\r\n"
4305 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4306 "Content-Length: 0\r\n\r\n"),
4307 // Server auth challenge.
4308 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4309 "Proxy-Connection: keep-alive\r\n"
4310 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4311 "Content-Length: 0\r\n\r\n"),
4312 // Response.
4313 MockRead("HTTP/1.1 200 OK\r\n"
4314 "Proxy-Connection: keep-alive\r\n"
4315 "Content-Length: 5\r\n\r\n"
4316 "hello"),
4317 // Response to second request.
4318 MockRead("HTTP/1.1 200 OK\r\n"
4319 "Proxy-Connection: keep-alive\r\n"
4320 "Content-Length: 2\r\n\r\n"
4321 "hi"),
4322 };
4323
4324 StaticSocketDataProvider data(data_reads, data_writes);
4325 session_deps_.socket_factory->AddSocketDataProvider(&data);
4326
4327 TestCompletionCallback callback;
4328
4329 auto trans =
4330 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4331 int rv = trans->Start(&request, callback.callback(), log.bound());
4332 EXPECT_THAT(callback.GetResult(rv), IsOk());
4333 const HttpResponseInfo* response = trans->GetResponseInfo();
4334 ASSERT_TRUE(response);
4335 ASSERT_TRUE(response->headers);
4336 EXPECT_EQ(407, response->headers->response_code());
4337 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4338
4339 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4340 EXPECT_THAT(callback.GetResult(rv), IsOk());
4341 response = trans->GetResponseInfo();
4342 ASSERT_TRUE(response);
4343 EXPECT_EQ(401, response->headers->response_code());
4344 EXPECT_FALSE(response->auth_challenge->is_proxy);
4345 EXPECT_EQ("http://myproxy:70",
4346 response->auth_challenge->challenger.Serialize());
4347 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4348 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4349
4350 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4351 callback.callback());
4352 EXPECT_THAT(callback.GetResult(rv), IsOk());
4353 response = trans->GetResponseInfo();
4354 ASSERT_TRUE(response);
4355 EXPECT_EQ(200, response->headers->response_code());
4356 // The password prompt info should not be set.
4357 EXPECT_FALSE(response->auth_challenge.has_value());
4358
4359 std::string response_data;
4360 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4361 EXPECT_EQ("hello", response_data);
4362
4363 // Check that the credentials were cached correctly.
4364 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4365 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264366 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334367 ASSERT_TRUE(entry);
4368 ASSERT_EQ(kFoo, entry->credentials().username());
4369 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264370 entry = session->http_auth_cache()->Lookup(
4371 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4372 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334373 ASSERT_TRUE(entry);
4374 ASSERT_EQ(kFoo2, entry->credentials().username());
4375 ASSERT_EQ(kBar2, entry->credentials().password());
4376
4377 // Make another request, which should automatically send the correct proxy and
4378 // server auth credentials and get another response.
4379 trans =
4380 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4381 rv = trans->Start(&request, callback.callback(), log.bound());
4382 EXPECT_THAT(callback.GetResult(rv), IsOk());
4383 response = trans->GetResponseInfo();
4384 ASSERT_TRUE(response);
4385 EXPECT_EQ(200, response->headers->response_code());
4386 // The password prompt info should not be set.
4387 EXPECT_FALSE(response->auth_challenge.has_value());
4388
4389 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4390 EXPECT_EQ("hi", response_data);
4391
4392 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114393 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menke96092e62019-10-18 04:09:334394}
4395
Matt Menkebe090422019-10-18 20:25:264396// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4397// are the same, but the user/passwords are different, and with different
4398// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4399// and auth challenges, sends another request with another NIK, expecting only
4400// the proxy credentials to be cached, and thus sees only a server auth
4401// challenge. Then sends a request with the original NIK, expecting cached proxy
4402// and auth credentials that match the ones used in the first request.
4403//
4404// Serves to verify credentials are correctly separated based on
4405// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4406// affects server credentials, not proxy credentials.
4407TEST_F(HttpNetworkTransactionTest,
4408 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
Matt Menke4807a9a2020-11-21 00:14:414409 const SchemefulSite kSite1(GURL("https://foo.test/"));
4410 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4411 const SchemefulSite kSite2(GURL("https://bar.test/"));
4412 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
Matt Menkebe090422019-10-18 20:25:264413
4414 // This test would need to use a single socket without this option enabled.
4415 // Best to use this option when it would affect a test, as it will eventually
4416 // become the default behavior.
4417 base::test::ScopedFeatureList feature_list;
4418 feature_list.InitAndEnableFeature(
4419 features::kPartitionConnectionsByNetworkIsolationKey);
4420
4421 // Proxy matches request URL.
4422 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564423 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264424 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144425 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264426 session_deps_.net_log = log.bound().net_log();
4427 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4429
4430 MockWrite data_writes[] = {
4431 // Initial request gets a proxy auth challenge.
4432 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4433 "Host: myproxy:70\r\n"
4434 "Proxy-Connection: keep-alive\r\n\r\n"),
4435 // Retry with proxy auth credentials, which will result in a server auth
4436 // challenge.
4437 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4438 "Host: myproxy:70\r\n"
4439 "Proxy-Connection: keep-alive\r\n"
4440 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4441 // Retry with proxy and server auth credentials, which gets a response.
4442 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4443 "Host: myproxy:70\r\n"
4444 "Proxy-Connection: keep-alive\r\n"
4445 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4446 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4447 // Another request to the same server and using the same NIK should
4448 // preemptively send the correct cached proxy and server
4449 // auth headers.
4450 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4451 "Host: myproxy:70\r\n"
4452 "Proxy-Connection: keep-alive\r\n"
4453 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4454 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4455 };
4456
4457 MockRead data_reads[] = {
4458 // Proxy auth challenge.
4459 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4460 "Proxy-Connection: keep-alive\r\n"
4461 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4462 "Content-Length: 0\r\n\r\n"),
4463 // Server auth challenge.
4464 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4465 "Proxy-Connection: keep-alive\r\n"
4466 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4467 "Content-Length: 0\r\n\r\n"),
4468 // Response.
4469 MockRead("HTTP/1.1 200 OK\r\n"
4470 "Proxy-Connection: keep-alive\r\n"
4471 "Content-Length: 5\r\n\r\n"
4472 "hello"),
4473 // Response to second request.
4474 MockRead("HTTP/1.1 200 OK\r\n"
4475 "Proxy-Connection: keep-alive\r\n"
4476 "Content-Length: 2\r\n\r\n"
4477 "hi"),
4478 };
4479
4480 StaticSocketDataProvider data(data_reads, data_writes);
4481 session_deps_.socket_factory->AddSocketDataProvider(&data);
4482
4483 MockWrite data_writes2[] = {
4484 // Initial request using a different NetworkIsolationKey includes the
4485 // cached proxy credentials, but not server credentials.
4486 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4487 "Host: myproxy:70\r\n"
4488 "Proxy-Connection: keep-alive\r\n"
4489 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4490 // Retry with proxy and new server auth credentials, which gets a
4491 // response.
4492 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4493 "Host: myproxy:70\r\n"
4494 "Proxy-Connection: keep-alive\r\n"
4495 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4496 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4497 };
4498
4499 MockRead data_reads2[] = {
4500 // Server auth challenge.
4501 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4502 "Proxy-Connection: keep-alive\r\n"
4503 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4504 "Content-Length: 0\r\n\r\n"),
4505 // Response.
4506 MockRead("HTTP/1.1 200 OK\r\n"
4507 "Proxy-Connection: keep-alive\r\n"
4508 "Content-Length: 9\r\n\r\n"
4509 "greetings"),
4510 };
4511
4512 StaticSocketDataProvider data2(data_reads2, data_writes2);
4513 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4514
4515 TestCompletionCallback callback;
4516
4517 HttpRequestInfo request;
4518 request.method = "GET";
4519 request.url = GURL("http://myproxy:70/");
4520 request.traffic_annotation =
4521 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4522 request.network_isolation_key = kNetworkIsolationKey1;
4523
4524 auto trans =
4525 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4526 int rv = trans->Start(&request, callback.callback(), log.bound());
4527 EXPECT_THAT(callback.GetResult(rv), IsOk());
4528 const HttpResponseInfo* response = trans->GetResponseInfo();
4529 ASSERT_TRUE(response);
4530 ASSERT_TRUE(response->headers);
4531 EXPECT_EQ(407, response->headers->response_code());
4532 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4533
4534 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4535 EXPECT_THAT(callback.GetResult(rv), IsOk());
4536 response = trans->GetResponseInfo();
4537 ASSERT_TRUE(response);
4538 EXPECT_EQ(401, response->headers->response_code());
4539 EXPECT_FALSE(response->auth_challenge->is_proxy);
4540 EXPECT_EQ("http://myproxy:70",
4541 response->auth_challenge->challenger.Serialize());
4542 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4543 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4544
4545 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4546 callback.callback());
4547 EXPECT_THAT(callback.GetResult(rv), IsOk());
4548 response = trans->GetResponseInfo();
4549 ASSERT_TRUE(response);
4550 EXPECT_EQ(200, response->headers->response_code());
4551 // The password prompt info should not be set.
4552 EXPECT_FALSE(response->auth_challenge.has_value());
4553 std::string response_data;
4554 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4555 EXPECT_EQ("hello", response_data);
4556
4557 // Check that the proxy credentials were cached correctly. The should be
4558 // accessible with any NetworkIsolationKey.
4559 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4560 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4561 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4562 ASSERT_TRUE(entry);
4563 ASSERT_EQ(kFoo, entry->credentials().username());
4564 ASSERT_EQ(kBar, entry->credentials().password());
4565 EXPECT_EQ(entry,
4566 session->http_auth_cache()->Lookup(
4567 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4568 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4569
4570 // Check that the server credentials were cached correctly. The should be
4571 // accessible with only kNetworkIsolationKey1.
4572 entry = session->http_auth_cache()->Lookup(
4573 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4574 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4575 ASSERT_TRUE(entry);
4576 ASSERT_EQ(kFoo2, entry->credentials().username());
4577 ASSERT_EQ(kBar2, entry->credentials().password());
4578 // Looking up the server entry with another NetworkIsolationKey should fail.
4579 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4580 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4581 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4582
4583 // Make another request with a different NetworkIsolationKey. It should use
4584 // another socket, reuse the cached proxy credentials, but result in a server
4585 // auth challenge.
4586 request.network_isolation_key = kNetworkIsolationKey2;
4587 trans =
4588 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4589 rv = trans->Start(&request, callback.callback(), log.bound());
4590 EXPECT_THAT(callback.GetResult(rv), IsOk());
4591 response = trans->GetResponseInfo();
4592 ASSERT_TRUE(response);
4593 EXPECT_EQ(401, response->headers->response_code());
4594 EXPECT_FALSE(response->auth_challenge->is_proxy);
4595 EXPECT_EQ("http://myproxy:70",
4596 response->auth_challenge->challenger.Serialize());
4597 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4598 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4599
4600 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4601 callback.callback());
4602 EXPECT_THAT(callback.GetResult(rv), IsOk());
4603 response = trans->GetResponseInfo();
4604 ASSERT_TRUE(response);
4605 EXPECT_EQ(200, response->headers->response_code());
4606 // The password prompt info should not be set.
4607 EXPECT_FALSE(response->auth_challenge.has_value());
4608 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4609 EXPECT_EQ("greetings", response_data);
4610
4611 // Check that the proxy credentials are still cached.
4612 entry = session->http_auth_cache()->Lookup(
4613 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4614 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4615 ASSERT_TRUE(entry);
4616 ASSERT_EQ(kFoo, entry->credentials().username());
4617 ASSERT_EQ(kBar, entry->credentials().password());
4618 EXPECT_EQ(entry,
4619 session->http_auth_cache()->Lookup(
4620 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4621 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4622
4623 // Check that the correct server credentials are cached for each
4624 // NetworkIsolationKey.
4625 entry = session->http_auth_cache()->Lookup(
4626 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4627 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4628 ASSERT_TRUE(entry);
4629 ASSERT_EQ(kFoo2, entry->credentials().username());
4630 ASSERT_EQ(kBar2, entry->credentials().password());
4631 entry = session->http_auth_cache()->Lookup(
4632 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4633 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4634 ASSERT_TRUE(entry);
4635 ASSERT_EQ(kFoo3, entry->credentials().username());
4636 ASSERT_EQ(kBar3, entry->credentials().password());
4637
4638 // Make a request with the original NetworkIsolationKey. It should reuse the
4639 // first socket, and the proxy credentials sent on the first socket.
4640 request.network_isolation_key = kNetworkIsolationKey1;
4641 trans =
4642 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4643 rv = trans->Start(&request, callback.callback(), log.bound());
4644 EXPECT_THAT(callback.GetResult(rv), IsOk());
4645 response = trans->GetResponseInfo();
4646 ASSERT_TRUE(response);
4647 EXPECT_EQ(200, response->headers->response_code());
4648 // The password prompt info should not be set.
4649 EXPECT_FALSE(response->auth_challenge.has_value());
4650 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4651 EXPECT_EQ("hi", response_data);
4652
4653 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114654 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264655}
4656
4657// Much like the test above, but uses tunnelled connections.
4658TEST_F(HttpNetworkTransactionTest,
4659 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
Matt Menke4807a9a2020-11-21 00:14:414660 const SchemefulSite kSite1(GURL("https://foo.test/"));
4661 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4662 const SchemefulSite kSite2(GURL("https://bar.test/"));
4663 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
Matt Menkebe090422019-10-18 20:25:264664
4665 // This test would need to use a single socket without this option enabled.
4666 // Best to use this option when it would affect a test, as it will eventually
4667 // become the default behavior.
4668 base::test::ScopedFeatureList feature_list;
4669 feature_list.InitAndEnableFeature(
4670 features::kPartitionConnectionsByNetworkIsolationKey);
4671
4672 // Proxy matches request URL.
4673 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564674 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264675 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144676 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264677 session_deps_.net_log = log.bound().net_log();
4678 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4679 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4680
4681 MockWrite data_writes[] = {
4682 // Initial tunnel request gets a proxy auth challenge.
4683 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4684 "Host: myproxy:70\r\n"
4685 "Proxy-Connection: keep-alive\r\n\r\n"),
4686 // Retry with proxy auth credentials, which will result in establishing a
4687 // tunnel.
4688 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4689 "Host: myproxy:70\r\n"
4690 "Proxy-Connection: keep-alive\r\n"
4691 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4692 // Request over the tunnel, which gets a server auth challenge.
4693 MockWrite("GET / HTTP/1.1\r\n"
4694 "Host: myproxy:70\r\n"
4695 "Connection: keep-alive\r\n\r\n"),
4696 // Retry with server auth credentials, which gets a response.
4697 MockWrite("GET / HTTP/1.1\r\n"
4698 "Host: myproxy:70\r\n"
4699 "Connection: keep-alive\r\n"
4700 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4701 // Another request to the same server and using the same NIK should
4702 // preemptively send the correct cached server
4703 // auth header. Since a tunnel was already established, the proxy headers
4704 // won't be sent again except when establishing another tunnel.
4705 MockWrite("GET / HTTP/1.1\r\n"
4706 "Host: myproxy:70\r\n"
4707 "Connection: keep-alive\r\n"
4708 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4709 };
4710
4711 MockRead data_reads[] = {
4712 // Proxy auth challenge.
4713 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4714 "Proxy-Connection: keep-alive\r\n"
4715 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4716 "Content-Length: 0\r\n\r\n"),
4717 // Tunnel success
4718 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4719 // Server auth challenge.
4720 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4721 "Connection: keep-alive\r\n"
4722 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4723 "Content-Length: 0\r\n\r\n"),
4724 // Response.
4725 MockRead("HTTP/1.1 200 OK\r\n"
4726 "Connection: keep-alive\r\n"
4727 "Content-Length: 5\r\n\r\n"
4728 "hello"),
4729 // Response to second request.
4730 MockRead("HTTP/1.1 200 OK\r\n"
4731 "Connection: keep-alive\r\n"
4732 "Content-Length: 2\r\n\r\n"
4733 "hi"),
4734 };
4735
4736 StaticSocketDataProvider data(data_reads, data_writes);
4737 session_deps_.socket_factory->AddSocketDataProvider(&data);
4738 // One for the proxy connection, one of the server connection.
4739 SSLSocketDataProvider ssl(ASYNC, OK);
4740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4741 SSLSocketDataProvider ssl2(ASYNC, OK);
4742 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4743
4744 MockWrite data_writes2[] = {
4745 // Initial request using a different NetworkIsolationKey includes the
4746 // cached proxy credentials when establishing a tunnel.
4747 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4748 "Host: myproxy:70\r\n"
4749 "Proxy-Connection: keep-alive\r\n"
4750 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4751 // Request over the tunnel, which gets a server auth challenge. Cached
4752 // credentials cannot be used, since the NIK is different.
4753 MockWrite("GET / HTTP/1.1\r\n"
4754 "Host: myproxy:70\r\n"
4755 "Connection: keep-alive\r\n\r\n"),
4756 // Retry with server auth credentials, which gets a response.
4757 MockWrite("GET / HTTP/1.1\r\n"
4758 "Host: myproxy:70\r\n"
4759 "Connection: keep-alive\r\n"
4760 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4761 };
4762
4763 MockRead data_reads2[] = {
4764 // Tunnel success
4765 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4766 // Server auth challenge.
4767 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4768 "Connection: keep-alive\r\n"
4769 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4770 "Content-Length: 0\r\n\r\n"),
4771 // Response.
4772 MockRead("HTTP/1.1 200 OK\r\n"
4773 "Connection: keep-alive\r\n"
4774 "Content-Length: 9\r\n\r\n"
4775 "greetings"),
4776 };
4777
4778 StaticSocketDataProvider data2(data_reads2, data_writes2);
4779 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4780 // One for the proxy connection, one of the server connection.
4781 SSLSocketDataProvider ssl3(ASYNC, OK);
4782 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4783 SSLSocketDataProvider ssl4(ASYNC, OK);
4784 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4785
4786 TestCompletionCallback callback;
4787
4788 HttpRequestInfo request;
4789 request.method = "GET";
4790 request.url = GURL("https://myproxy:70/");
4791 request.traffic_annotation =
4792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4793 request.network_isolation_key = kNetworkIsolationKey1;
4794
4795 auto trans =
4796 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4797 int rv = trans->Start(&request, callback.callback(), log.bound());
4798 EXPECT_THAT(callback.GetResult(rv), IsOk());
4799 const HttpResponseInfo* response = trans->GetResponseInfo();
4800 ASSERT_TRUE(response);
4801 ASSERT_TRUE(response->headers);
4802 EXPECT_EQ(407, response->headers->response_code());
4803 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4804
4805 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4806 EXPECT_THAT(callback.GetResult(rv), IsOk());
4807 response = trans->GetResponseInfo();
4808 ASSERT_TRUE(response);
4809 EXPECT_EQ(401, response->headers->response_code());
4810 EXPECT_FALSE(response->auth_challenge->is_proxy);
4811 EXPECT_EQ("https://myproxy:70",
4812 response->auth_challenge->challenger.Serialize());
4813 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4814 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4815
4816 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4817 callback.callback());
4818 EXPECT_THAT(callback.GetResult(rv), IsOk());
4819 response = trans->GetResponseInfo();
4820 ASSERT_TRUE(response);
4821 EXPECT_EQ(200, response->headers->response_code());
4822 // The password prompt info should not be set.
4823 EXPECT_FALSE(response->auth_challenge.has_value());
4824 std::string response_data;
4825 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4826 EXPECT_EQ("hello", response_data);
4827
4828 // Check that the proxy credentials were cached correctly. The should be
4829 // accessible with any NetworkIsolationKey.
4830 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4831 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4832 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4833 ASSERT_TRUE(entry);
4834 ASSERT_EQ(kFoo, entry->credentials().username());
4835 ASSERT_EQ(kBar, entry->credentials().password());
4836 EXPECT_EQ(entry,
4837 session->http_auth_cache()->Lookup(
4838 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4839 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4840
4841 // Check that the server credentials were cached correctly. The should be
4842 // accessible with only kNetworkIsolationKey1.
4843 entry = session->http_auth_cache()->Lookup(
4844 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4845 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4846 ASSERT_TRUE(entry);
4847 ASSERT_EQ(kFoo2, entry->credentials().username());
4848 ASSERT_EQ(kBar2, entry->credentials().password());
4849 // Looking up the server entry with another NetworkIsolationKey should fail.
4850 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4851 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4852 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4853
4854 // Make another request with a different NetworkIsolationKey. It should use
4855 // another socket, reuse the cached proxy credentials, but result in a server
4856 // auth challenge.
4857 request.network_isolation_key = kNetworkIsolationKey2;
4858 trans =
4859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4860 rv = trans->Start(&request, callback.callback(), log.bound());
4861 EXPECT_THAT(callback.GetResult(rv), IsOk());
4862 response = trans->GetResponseInfo();
4863 ASSERT_TRUE(response);
4864 EXPECT_EQ(401, response->headers->response_code());
4865 EXPECT_FALSE(response->auth_challenge->is_proxy);
4866 EXPECT_EQ("https://myproxy:70",
4867 response->auth_challenge->challenger.Serialize());
4868 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4869 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4870
4871 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4872 callback.callback());
4873 EXPECT_THAT(callback.GetResult(rv), IsOk());
4874 response = trans->GetResponseInfo();
4875 ASSERT_TRUE(response);
4876 EXPECT_EQ(200, response->headers->response_code());
4877 // The password prompt info should not be set.
4878 EXPECT_FALSE(response->auth_challenge.has_value());
4879 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4880 EXPECT_EQ("greetings", response_data);
4881
4882 // Check that the proxy credentials are still cached.
4883 entry = session->http_auth_cache()->Lookup(
4884 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4885 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4886 ASSERT_TRUE(entry);
4887 ASSERT_EQ(kFoo, entry->credentials().username());
4888 ASSERT_EQ(kBar, entry->credentials().password());
4889 EXPECT_EQ(entry,
4890 session->http_auth_cache()->Lookup(
4891 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4892 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4893
4894 // Check that the correct server credentials are cached for each
4895 // NetworkIsolationKey.
4896 entry = session->http_auth_cache()->Lookup(
4897 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4898 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4899 ASSERT_TRUE(entry);
4900 ASSERT_EQ(kFoo2, entry->credentials().username());
4901 ASSERT_EQ(kBar2, entry->credentials().password());
4902 entry = session->http_auth_cache()->Lookup(
4903 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4904 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4905 ASSERT_TRUE(entry);
4906 ASSERT_EQ(kFoo3, entry->credentials().username());
4907 ASSERT_EQ(kBar3, entry->credentials().password());
4908
4909 // Make a request with the original NetworkIsolationKey. It should reuse the
4910 // first socket, and the proxy credentials sent on the first socket.
4911 request.network_isolation_key = kNetworkIsolationKey1;
4912 trans =
4913 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4914 rv = trans->Start(&request, callback.callback(), log.bound());
4915 EXPECT_THAT(callback.GetResult(rv), IsOk());
4916 response = trans->GetResponseInfo();
4917 ASSERT_TRUE(response);
4918 EXPECT_EQ(200, response->headers->response_code());
4919 // The password prompt info should not be set.
4920 EXPECT_FALSE(response->auth_challenge.has_value());
4921 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4922 EXPECT_EQ("hi", response_data);
4923
4924 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114925 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264926}
4927
ttuttle7933c112015-01-06 00:55:244928// Test that we don't pass extraneous headers from the proxy's response to the
4929// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014930TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244931 HttpRequestInfo request;
4932 request.method = "GET";
bncce36dca22015-04-21 22:11:234933 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104934 request.traffic_annotation =
4935 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244936
4937 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564938 session_deps_.proxy_resolution_service =
4939 ConfiguredProxyResolutionService::CreateFixed(
4940 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244941
danakj1fd259a02016-04-16 03:17:094942 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244943
bnc691fda62016-08-12 00:43:164944 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244945
4946 // Since we have proxy, should try to establish tunnel.
4947 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174948 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4949 "Host: www.example.org:443\r\n"
4950 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244951 };
4952
4953 // The proxy responds to the connect with a 407.
4954 MockRead data_reads[] = {
4955 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4956 MockRead("X-Foo: bar\r\n"),
4957 MockRead("Set-Cookie: foo=bar\r\n"),
4958 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4959 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234960 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244961 };
4962
Ryan Sleevib8d7ea02018-05-07 20:01:014963 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244964 session_deps_.socket_factory->AddSocketDataProvider(&data);
4965
4966 TestCompletionCallback callback;
4967
tfarina42834112016-09-22 13:38:204968 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014969 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244970
4971 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014972 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244973
bnc691fda62016-08-12 00:43:164974 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244975 ASSERT_TRUE(response);
4976 ASSERT_TRUE(response->headers);
4977 EXPECT_TRUE(response->headers->IsKeepAlive());
4978 EXPECT_EQ(407, response->headers->response_code());
4979 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4980 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4981 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4982
4983 std::string response_data;
bnc691fda62016-08-12 00:43:164984 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014985 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244986
4987 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114988 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle7933c112015-01-06 00:55:244989}
4990
[email protected]8fdbcd22010-05-05 02:54:524991// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4992// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014993TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524994 HttpRequestInfo request;
4995 request.method = "GET";
bncce36dca22015-04-21 22:11:234996 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104997 request.traffic_annotation =
4998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524999
[email protected]cb9bf6ca2011-01-28 13:15:275000 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:095001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:165002 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:275003
[email protected]8fdbcd22010-05-05 02:54:525004 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235005 MockWrite(
5006 "GET / HTTP/1.1\r\n"
5007 "Host: www.example.org\r\n"
5008 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:525009 };
5010
5011 MockRead data_reads1[] = {
5012 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
5013 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5014 // Large content-length -- won't matter, as connection will be reset.
5015 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065016 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:525017 };
5018
Ryan Sleevib8d7ea02018-05-07 20:01:015019 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075020 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:525021
[email protected]49639fa2011-12-20 23:22:415022 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:525023
tfarina42834112016-09-22 13:38:205024 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015025 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:525026
5027 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015028 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:525029}
5030
[email protected]7a67a8152010-11-05 18:31:105031// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
5032// through a non-authenticating proxy. The request should fail with
5033// ERR_UNEXPECTED_PROXY_AUTH.
5034// Note that it is impossible to detect if an HTTP server returns a 407 through
5035// a non-authenticating proxy - there is nothing to indicate whether the
5036// response came from the proxy or the server, so it is treated as if the proxy
5037// issued the challenge.
bncd16676a2016-07-20 16:23:015038TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:275039 HttpRequestInfo request;
5040 request.method = "GET";
bncce36dca22015-04-21 22:11:235041 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105042 request.traffic_annotation =
5043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275044
Nicolas Arciniegad2013f92020-02-07 23:00:565045 session_deps_.proxy_resolution_service =
5046 ConfiguredProxyResolutionService::CreateFixed(
5047 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145048 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075049 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095050 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:105051
[email protected]7a67a8152010-11-05 18:31:105052 // Since we have proxy, should try to establish tunnel.
5053 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175054 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5055 "Host: www.example.org:443\r\n"
5056 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:105057
rsleevidb16bb02015-11-12 23:47:175058 MockWrite("GET / HTTP/1.1\r\n"
5059 "Host: www.example.org\r\n"
5060 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:105061 };
5062
5063 MockRead data_reads1[] = {
5064 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5065
5066 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
5067 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5068 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:065069 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:105070 };
5071
Ryan Sleevib8d7ea02018-05-07 20:01:015072 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075073 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065074 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075075 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:105076
[email protected]49639fa2011-12-20 23:22:415077 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:105078
bnc691fda62016-08-12 00:43:165079 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:105080
bnc691fda62016-08-12 00:43:165081 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:105083
5084 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015085 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:545086 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:105087 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:005088 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
5089 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:105090 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:405091 entries, pos,
mikecirone8b85c432016-09-08 19:11:005092 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
5093 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:105094}
[email protected]2df19bb2010-08-25 20:13:465095
mmenke2a1781d2015-10-07 19:25:335096// Test a proxy auth scheme that allows default credentials and a proxy server
5097// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:015098TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335099 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
5100 HttpRequestInfo request;
5101 request.method = "GET";
5102 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105103 request.traffic_annotation =
5104 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335105
5106 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595107 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565108 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495109 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335110
Jeremy Roman0579ed62017-08-29 15:56:195111 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335112 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195113 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335114 mock_handler->set_allows_default_credentials(true);
5115 auth_handler_factory->AddMockHandler(mock_handler.release(),
5116 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485117 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335118
5119 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585120 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095121 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335122
5123 // Since we have proxy, should try to establish tunnel.
5124 MockWrite data_writes1[] = {
5125 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175126 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335127 "Proxy-Connection: keep-alive\r\n\r\n"),
5128 };
5129
5130 // The proxy responds to the connect with a 407, using a non-persistent
5131 // connection.
5132 MockRead data_reads1[] = {
5133 // No credentials.
5134 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5135 MockRead("Proxy-Authenticate: Mock\r\n"),
5136 MockRead("Proxy-Connection: close\r\n\r\n"),
5137 };
5138
5139 // Since the first connection couldn't be reused, need to establish another
5140 // once given credentials.
5141 MockWrite data_writes2[] = {
5142 // After calling trans->RestartWithAuth(), this is the request we should
5143 // be issuing -- the final header line contains the credentials.
5144 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175145 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335146 "Proxy-Connection: keep-alive\r\n"
5147 "Proxy-Authorization: auth_token\r\n\r\n"),
5148
5149 MockWrite("GET / HTTP/1.1\r\n"
5150 "Host: www.example.org\r\n"
5151 "Connection: keep-alive\r\n\r\n"),
5152 };
5153
5154 MockRead data_reads2[] = {
5155 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5156
5157 MockRead("HTTP/1.1 200 OK\r\n"),
5158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5159 MockRead("Content-Length: 5\r\n\r\n"),
5160 MockRead(SYNCHRONOUS, "hello"),
5161 };
5162
Ryan Sleevib8d7ea02018-05-07 20:01:015163 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335164 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015165 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335166 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5167 SSLSocketDataProvider ssl(ASYNC, OK);
5168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5169
bnc87dcefc2017-05-25 12:47:585170 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195171 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335172
5173 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205174 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015175 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335176
5177 const HttpResponseInfo* response = trans->GetResponseInfo();
5178 ASSERT_TRUE(response);
5179 ASSERT_TRUE(response->headers);
5180 EXPECT_FALSE(response->headers->IsKeepAlive());
5181 EXPECT_EQ(407, response->headers->response_code());
5182 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5183 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585184 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335185
5186 LoadTimingInfo load_timing_info;
5187 // CONNECT requests and responses are handled at the connect job level, so
5188 // the transaction does not yet have a connection.
5189 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5190
5191 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015192 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335193 response = trans->GetResponseInfo();
5194 ASSERT_TRUE(response);
5195 ASSERT_TRUE(response->headers);
5196 EXPECT_TRUE(response->headers->IsKeepAlive());
5197 EXPECT_EQ(200, response->headers->response_code());
5198 EXPECT_EQ(5, response->headers->GetContentLength());
5199 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5200
5201 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585202 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335203
5204 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5205 TestLoadTimingNotReusedWithPac(load_timing_info,
5206 CONNECT_TIMING_HAS_SSL_TIMES);
5207
5208 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115209 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335210}
5211
5212// Test a proxy auth scheme that allows default credentials and a proxy server
5213// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:015214TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335215 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
5216 HttpRequestInfo request;
5217 request.method = "GET";
5218 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105219 request.traffic_annotation =
5220 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335221
5222 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595223 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565224 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495225 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335226
Jeremy Roman0579ed62017-08-29 15:56:195227 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335228 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195229 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335230 mock_handler->set_allows_default_credentials(true);
5231 auth_handler_factory->AddMockHandler(mock_handler.release(),
5232 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485233 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335234
5235 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585236 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095237 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335238
5239 // Should try to establish tunnel.
5240 MockWrite data_writes1[] = {
5241 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175242 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335243 "Proxy-Connection: keep-alive\r\n\r\n"),
5244
5245 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175246 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335247 "Proxy-Connection: keep-alive\r\n"
5248 "Proxy-Authorization: auth_token\r\n\r\n"),
5249 };
5250
5251 // The proxy responds to the connect with a 407, using a non-persistent
5252 // connection.
5253 MockRead data_reads1[] = {
5254 // No credentials.
5255 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5256 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5257 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5258 };
5259
5260 // Since the first connection was closed, need to establish another once given
5261 // credentials.
5262 MockWrite data_writes2[] = {
5263 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175264 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335265 "Proxy-Connection: keep-alive\r\n"
5266 "Proxy-Authorization: auth_token\r\n\r\n"),
5267
5268 MockWrite("GET / HTTP/1.1\r\n"
5269 "Host: www.example.org\r\n"
5270 "Connection: keep-alive\r\n\r\n"),
5271 };
5272
5273 MockRead data_reads2[] = {
5274 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5275
5276 MockRead("HTTP/1.1 200 OK\r\n"),
5277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5278 MockRead("Content-Length: 5\r\n\r\n"),
5279 MockRead(SYNCHRONOUS, "hello"),
5280 };
5281
Ryan Sleevib8d7ea02018-05-07 20:01:015282 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335283 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015284 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335285 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5286 SSLSocketDataProvider ssl(ASYNC, OK);
5287 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5288
bnc87dcefc2017-05-25 12:47:585289 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195290 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335291
5292 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205293 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015294 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335295
5296 const HttpResponseInfo* response = trans->GetResponseInfo();
5297 ASSERT_TRUE(response);
5298 ASSERT_TRUE(response->headers);
5299 EXPECT_TRUE(response->headers->IsKeepAlive());
5300 EXPECT_EQ(407, response->headers->response_code());
5301 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5302 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585303 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335304
5305 LoadTimingInfo load_timing_info;
5306 // CONNECT requests and responses are handled at the connect job level, so
5307 // the transaction does not yet have a connection.
5308 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5309
5310 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015311 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335312
5313 response = trans->GetResponseInfo();
5314 ASSERT_TRUE(response);
5315 ASSERT_TRUE(response->headers);
5316 EXPECT_TRUE(response->headers->IsKeepAlive());
5317 EXPECT_EQ(200, response->headers->response_code());
5318 EXPECT_EQ(5, response->headers->GetContentLength());
5319 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5320
5321 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585322 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335323
5324 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5325 TestLoadTimingNotReusedWithPac(load_timing_info,
5326 CONNECT_TIMING_HAS_SSL_TIMES);
5327
5328 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115329 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335330}
5331
5332// Test a proxy auth scheme that allows default credentials and a proxy server
5333// that hangs up when credentials are initially sent, and hangs up again when
5334// they are retried.
bncd16676a2016-07-20 16:23:015335TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335336 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5337 HttpRequestInfo request;
5338 request.method = "GET";
5339 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105340 request.traffic_annotation =
5341 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335342
5343 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595344 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565345 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495346 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335347
Jeremy Roman0579ed62017-08-29 15:56:195348 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335349 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195350 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335351 mock_handler->set_allows_default_credentials(true);
5352 auth_handler_factory->AddMockHandler(mock_handler.release(),
5353 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485354 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335355
5356 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585357 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095358 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335359
5360 // Should try to establish tunnel.
5361 MockWrite data_writes1[] = {
5362 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175363 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335364 "Proxy-Connection: keep-alive\r\n\r\n"),
5365
5366 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175367 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335368 "Proxy-Connection: keep-alive\r\n"
5369 "Proxy-Authorization: auth_token\r\n\r\n"),
5370 };
5371
5372 // The proxy responds to the connect with a 407, and then hangs up after the
5373 // second request is sent.
5374 MockRead data_reads1[] = {
5375 // No credentials.
5376 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5377 MockRead("Content-Length: 0\r\n"),
5378 MockRead("Proxy-Connection: keep-alive\r\n"),
5379 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5380 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5381 };
5382
5383 // HttpNetworkTransaction sees a reused connection that was closed with
5384 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5385 // request.
5386 MockWrite data_writes2[] = {
5387 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175388 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335389 "Proxy-Connection: keep-alive\r\n\r\n"),
5390 };
5391
5392 // The proxy, having had more than enough of us, just hangs up.
5393 MockRead data_reads2[] = {
5394 // No credentials.
5395 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5396 };
5397
Ryan Sleevib8d7ea02018-05-07 20:01:015398 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335399 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015400 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335401 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5402
bnc87dcefc2017-05-25 12:47:585403 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195404 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335405
5406 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205407 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015408 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335409
5410 const HttpResponseInfo* response = trans->GetResponseInfo();
5411 ASSERT_TRUE(response);
5412 ASSERT_TRUE(response->headers);
5413 EXPECT_TRUE(response->headers->IsKeepAlive());
5414 EXPECT_EQ(407, response->headers->response_code());
5415 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5416 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585417 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335418
5419 LoadTimingInfo load_timing_info;
5420 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5421
5422 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015423 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335424
5425 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115426 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335427}
5428
Asanka Herathbc3f8f62018-11-16 23:08:305429// This test exercises an odd edge case where the proxy closes the connection
5430// after the authentication handshake is complete. Presumably this technique is
5431// used in lieu of returning a 403 or 5xx status code when the authentication
5432// succeeds, but the user is not authorized to connect to the destination
5433// server. There's no standard for what a proxy should do to indicate a blocked
5434// site.
5435TEST_F(HttpNetworkTransactionTest,
5436 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5437 HttpRequestInfo request;
5438 request.method = "GET";
5439 request.url = GURL("https://www.example.org/");
5440 request.traffic_annotation =
5441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5442
5443 // Configure against proxy server "myproxy:70".
5444 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565445 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Asanka Herathbc3f8f62018-11-16 23:08:305446 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5447
5448 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5449 auth_handler_factory->set_do_init_from_challenge(true);
5450
5451 // Create two mock AuthHandlers. This is because the transaction gets retried
5452 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5453 // was a real network error.
5454 //
5455 // The handlers support both default and explicit credentials. The retry
5456 // mentioned above should be able to reuse the default identity. Thus there
5457 // should never be a need to prompt for explicit credentials.
5458 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5459 mock_handler->set_allows_default_credentials(true);
5460 mock_handler->set_allows_explicit_credentials(true);
5461 mock_handler->set_connection_based(true);
5462 auth_handler_factory->AddMockHandler(mock_handler.release(),
5463 HttpAuth::AUTH_PROXY);
5464 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5465 mock_handler->set_allows_default_credentials(true);
5466 mock_handler->set_allows_explicit_credentials(true);
5467 mock_handler->set_connection_based(true);
5468 auth_handler_factory->AddMockHandler(mock_handler.release(),
5469 HttpAuth::AUTH_PROXY);
5470 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5471
Matt Muellerde5dadf2019-11-27 20:11:585472 session_deps_.net_log = NetLog::Get();
Asanka Herathbc3f8f62018-11-16 23:08:305473 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5474
5475 // Data for both sockets.
5476 //
5477 // Writes are for the tunnel establishment attempts and the
5478 // authentication handshake.
5479 MockWrite data_writes1[] = {
5480 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5481 "Host: www.example.org:443\r\n"
5482 "Proxy-Connection: keep-alive\r\n\r\n"),
5483
5484 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5485 "Host: www.example.org:443\r\n"
5486 "Proxy-Connection: keep-alive\r\n"
5487 "Proxy-Authorization: auth_token\r\n\r\n"),
5488
5489 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5490 "Host: www.example.org:443\r\n"
5491 "Proxy-Connection: keep-alive\r\n"
5492 "Proxy-Authorization: auth_token\r\n\r\n"),
5493 };
5494
5495 // The server side of the authentication handshake. Note that the response to
5496 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5497 MockRead data_reads1[] = {
5498 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5499 MockRead("Content-Length: 0\r\n"),
5500 MockRead("Proxy-Connection: keep-alive\r\n"),
5501 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5502
5503 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5504 MockRead("Content-Length: 0\r\n"),
5505 MockRead("Proxy-Connection: keep-alive\r\n"),
5506 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5507
5508 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5509 };
5510
5511 StaticSocketDataProvider data1(data_reads1, data_writes1);
5512 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5513
5514 // The second socket is for the reconnection attempt. Data is identical to the
5515 // first attempt.
5516 StaticSocketDataProvider data2(data_reads1, data_writes1);
5517 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5518
5519 auto trans =
5520 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5521
5522 TestCompletionCallback callback;
5523 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5524
5525 // Two rounds per handshake. After one retry, the error is propagated up the
5526 // stack.
5527 for (int i = 0; i < 4; ++i) {
5528 EXPECT_THAT(callback.GetResult(rv), IsOk());
5529
5530 const HttpResponseInfo* response = trans->GetResponseInfo();
5531 ASSERT_TRUE(response);
5532 ASSERT_TRUE(response->headers);
5533 EXPECT_EQ(407, response->headers->response_code());
5534 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5535
5536 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5537 }
5538
5539 // One shall be the number thou shalt retry, and the number of the retrying
5540 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5541 // that thou then proceed to one. Three is right out. Once the number one,
5542 // being the first number, be reached, then lobbest thou thy
5543 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5544 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5545
5546 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115547 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Asanka Herathbc3f8f62018-11-16 23:08:305548}
5549
mmenke2a1781d2015-10-07 19:25:335550// Test a proxy auth scheme that allows default credentials and a proxy server
5551// that hangs up when credentials are initially sent, and sends a challenge
5552// again they are retried.
bncd16676a2016-07-20 16:23:015553TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335554 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5555 HttpRequestInfo request;
5556 request.method = "GET";
5557 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105558 request.traffic_annotation =
5559 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335560
5561 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595562 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565563 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495564 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335565
Jeremy Roman0579ed62017-08-29 15:56:195566 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335567 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195568 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335569 mock_handler->set_allows_default_credentials(true);
5570 auth_handler_factory->AddMockHandler(mock_handler.release(),
5571 HttpAuth::AUTH_PROXY);
5572 // Add another handler for the second challenge. It supports default
5573 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195574 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335575 mock_handler->set_allows_default_credentials(true);
5576 auth_handler_factory->AddMockHandler(mock_handler.release(),
5577 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485578 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335579
5580 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585581 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095582 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335583
5584 // Should try to establish tunnel.
5585 MockWrite data_writes1[] = {
5586 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175587 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335588 "Proxy-Connection: keep-alive\r\n\r\n"),
5589 };
5590
5591 // The proxy responds to the connect with a 407, using a non-persistent
5592 // connection.
5593 MockRead data_reads1[] = {
5594 // No credentials.
5595 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5596 MockRead("Proxy-Authenticate: Mock\r\n"),
5597 MockRead("Proxy-Connection: close\r\n\r\n"),
5598 };
5599
5600 // Since the first connection was closed, need to establish another once given
5601 // credentials.
5602 MockWrite data_writes2[] = {
5603 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175604 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335605 "Proxy-Connection: keep-alive\r\n"
5606 "Proxy-Authorization: auth_token\r\n\r\n"),
5607 };
5608
5609 MockRead data_reads2[] = {
5610 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5611 MockRead("Proxy-Authenticate: Mock\r\n"),
5612 MockRead("Proxy-Connection: close\r\n\r\n"),
5613 };
5614
Ryan Sleevib8d7ea02018-05-07 20:01:015615 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335616 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015617 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335618 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5619 SSLSocketDataProvider ssl(ASYNC, OK);
5620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5621
bnc87dcefc2017-05-25 12:47:585622 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195623 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335624
5625 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205626 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015627 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335628
5629 const HttpResponseInfo* response = trans->GetResponseInfo();
5630 ASSERT_TRUE(response);
5631 ASSERT_TRUE(response->headers);
5632 EXPECT_EQ(407, response->headers->response_code());
5633 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5634 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585635 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335636
5637 LoadTimingInfo load_timing_info;
5638 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5639
5640 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015641 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335642 response = trans->GetResponseInfo();
5643 ASSERT_TRUE(response);
5644 ASSERT_TRUE(response->headers);
5645 EXPECT_EQ(407, response->headers->response_code());
5646 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585647 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335648
5649 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115650 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335651}
5652
asankae2257db2016-10-11 22:03:165653// A more nuanced test than GenerateAuthToken test which asserts that
5654// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5655// unnecessarily invalidated, and that if the server co-operates, the
5656// authentication handshake can continue with the same scheme but with a
5657// different identity.
5658TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5659 HttpRequestInfo request;
5660 request.method = "GET";
5661 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105662 request.traffic_annotation =
5663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165664
Jeremy Roman0579ed62017-08-29 15:56:195665 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165666 auth_handler_factory->set_do_init_from_challenge(true);
5667
5668 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195669 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165670 mock_handler->set_allows_default_credentials(true);
5671 mock_handler->set_allows_explicit_credentials(true);
5672 mock_handler->set_connection_based(true);
5673 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5674 auth_handler_factory->AddMockHandler(mock_handler.release(),
5675 HttpAuth::AUTH_SERVER);
5676
5677 // Add another handler for the second challenge. It supports default
5678 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195679 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165680 mock_handler->set_allows_default_credentials(true);
5681 mock_handler->set_allows_explicit_credentials(true);
5682 mock_handler->set_connection_based(true);
5683 auth_handler_factory->AddMockHandler(mock_handler.release(),
5684 HttpAuth::AUTH_SERVER);
5685 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5686
5687 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5688
5689 MockWrite data_writes1[] = {
5690 MockWrite("GET / HTTP/1.1\r\n"
5691 "Host: www.example.org\r\n"
5692 "Connection: keep-alive\r\n\r\n"),
5693 };
5694
5695 MockRead data_reads1[] = {
5696 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5697 "WWW-Authenticate: Mock\r\n"
5698 "Connection: keep-alive\r\n\r\n"),
5699 };
5700
5701 // Identical to data_writes1[]. The AuthHandler encounters a
5702 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5703 // transaction procceds without an authorization header.
5704 MockWrite data_writes2[] = {
5705 MockWrite("GET / HTTP/1.1\r\n"
5706 "Host: www.example.org\r\n"
5707 "Connection: keep-alive\r\n\r\n"),
5708 };
5709
5710 MockRead data_reads2[] = {
5711 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5712 "WWW-Authenticate: Mock\r\n"
5713 "Connection: keep-alive\r\n\r\n"),
5714 };
5715
5716 MockWrite data_writes3[] = {
5717 MockWrite("GET / HTTP/1.1\r\n"
5718 "Host: www.example.org\r\n"
5719 "Connection: keep-alive\r\n"
5720 "Authorization: auth_token\r\n\r\n"),
5721 };
5722
5723 MockRead data_reads3[] = {
5724 MockRead("HTTP/1.1 200 OK\r\n"
5725 "Content-Length: 5\r\n"
5726 "Content-Type: text/plain\r\n"
5727 "Connection: keep-alive\r\n\r\n"
5728 "Hello"),
5729 };
5730
Ryan Sleevib8d7ea02018-05-07 20:01:015731 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165732 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5733
Ryan Sleevib8d7ea02018-05-07 20:01:015734 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165735 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5736
Ryan Sleevib8d7ea02018-05-07 20:01:015737 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165738 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5739
bnc87dcefc2017-05-25 12:47:585740 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195741 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165742
5743 TestCompletionCallback callback;
5744 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5745 EXPECT_THAT(callback.GetResult(rv), IsOk());
5746
5747 const HttpResponseInfo* response = trans->GetResponseInfo();
5748 ASSERT_TRUE(response);
5749 ASSERT_TRUE(response->headers);
5750 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5751
5752 // The following three tests assert that an authentication challenge was
5753 // received and that the stack is ready to respond to the challenge using
5754 // ambient credentials.
5755 EXPECT_EQ(401, response->headers->response_code());
5756 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585757 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165758
5759 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5760 EXPECT_THAT(callback.GetResult(rv), IsOk());
5761 response = trans->GetResponseInfo();
5762 ASSERT_TRUE(response);
5763 ASSERT_TRUE(response->headers);
5764
5765 // The following three tests assert that an authentication challenge was
5766 // received and that the stack needs explicit credentials before it is ready
5767 // to respond to the challenge.
5768 EXPECT_EQ(401, response->headers->response_code());
5769 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585770 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165771
5772 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5773 EXPECT_THAT(callback.GetResult(rv), IsOk());
5774 response = trans->GetResponseInfo();
5775 ASSERT_TRUE(response);
5776 ASSERT_TRUE(response->headers);
5777 EXPECT_EQ(200, response->headers->response_code());
5778
5779 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115780 session->CloseAllConnections(ERR_FAILED, "Very good reason");
asankae2257db2016-10-11 22:03:165781}
5782
Matt Menked1eb6d42018-01-17 04:54:065783// Proxy resolver that returns a proxy with the same host and port for different
5784// schemes, based on the path of the URL being requests.
5785class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5786 public:
5787 SameProxyWithDifferentSchemesProxyResolver() {}
5788 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5789
Titouan Rigoudyba507a882020-07-31 12:15:155790 static constexpr uint16_t kProxyPort = 10000;
Matt Menked1eb6d42018-01-17 04:54:065791
5792 static HostPortPair ProxyHostPortPair() {
Titouan Rigoudyba507a882020-07-31 12:15:155793 return HostPortPair("proxy.test", kProxyPort);
5794 }
5795
5796 static std::string ProxyHostPortPairAsString() {
5797 return ProxyHostPortPair().ToString();
Matt Menked1eb6d42018-01-17 04:54:065798 }
5799
5800 // ProxyResolver implementation.
5801 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:395802 const NetworkIsolationKey& network_isolation_key,
Matt Menked1eb6d42018-01-17 04:54:065803 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175804 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065805 std::unique_ptr<Request>* request,
5806 const NetLogWithSource& /*net_log*/) override {
5807 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575808 results->set_traffic_annotation(
5809 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065810 if (url.path() == "/socks4") {
5811 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5812 return OK;
5813 }
5814 if (url.path() == "/socks5") {
5815 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5816 return OK;
5817 }
5818 if (url.path() == "/http") {
5819 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5820 return OK;
5821 }
5822 if (url.path() == "/https") {
5823 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5824 return OK;
5825 }
Matt Menkee8648fa2019-01-17 16:47:075826 if (url.path() == "/https_trusted") {
5827 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5828 ProxyHostPortPair(),
5829 true /* is_trusted_proxy */));
5830 return OK;
5831 }
Matt Menked1eb6d42018-01-17 04:54:065832 NOTREACHED();
5833 return ERR_NOT_IMPLEMENTED;
5834 }
5835
5836 private:
5837 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5838};
5839
5840class SameProxyWithDifferentSchemesProxyResolverFactory
5841 : public ProxyResolverFactory {
5842 public:
5843 SameProxyWithDifferentSchemesProxyResolverFactory()
5844 : ProxyResolverFactory(false) {}
5845
Lily Houghton99597862018-03-07 16:40:425846 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5847 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175848 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425849 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065850 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5851 return OK;
5852 }
5853
5854 private:
5855 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5856};
5857
5858// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075859// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065860// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5861// request to foo.com using proxy.com as an HTTP proxy.
5862TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495863 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565864 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:495865 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5866 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5867 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
Eric Roman3be01ba2020-04-03 21:37:095868 nullptr, /*quick_check_enabled=*/true);
Matt Menked1eb6d42018-01-17 04:54:065869
5870 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5871
5872 MockWrite socks_writes[] = {
5873 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5874 kSOCKS4OkRequestLocalHostPort80Length),
5875 MockWrite(SYNCHRONOUS,
5876 "GET /socks4 HTTP/1.1\r\n"
5877 "Host: test\r\n"
5878 "Connection: keep-alive\r\n\r\n"),
5879 };
5880 MockRead socks_reads[] = {
5881 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5882 MockRead("HTTP/1.0 200 OK\r\n"
5883 "Connection: keep-alive\r\n"
5884 "Content-Length: 15\r\n\r\n"
5885 "SOCKS4 Response"),
5886 };
Ryan Sleevib8d7ea02018-05-07 20:01:015887 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065888 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5889
5890 const char kSOCKS5Request[] = {
5891 0x05, // Version
5892 0x01, // Command (CONNECT)
5893 0x00, // Reserved
5894 0x03, // Address type (DOMAINNAME)
5895 0x04, // Length of domain (4)
5896 't', 'e', 's', 't', // Domain string
5897 0x00, 0x50, // 16-bit port (80)
5898 };
5899 MockWrite socks5_writes[] = {
5900 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245901 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065902 MockWrite(SYNCHRONOUS,
5903 "GET /socks5 HTTP/1.1\r\n"
5904 "Host: test\r\n"
5905 "Connection: keep-alive\r\n\r\n"),
5906 };
5907 MockRead socks5_reads[] = {
5908 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5909 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5910 MockRead("HTTP/1.0 200 OK\r\n"
5911 "Connection: keep-alive\r\n"
5912 "Content-Length: 15\r\n\r\n"
5913 "SOCKS5 Response"),
5914 };
Ryan Sleevib8d7ea02018-05-07 20:01:015915 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065916 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5917
5918 MockWrite http_writes[] = {
5919 MockWrite(SYNCHRONOUS,
5920 "GET http://test/http HTTP/1.1\r\n"
5921 "Host: test\r\n"
5922 "Proxy-Connection: keep-alive\r\n\r\n"),
5923 };
5924 MockRead http_reads[] = {
5925 MockRead("HTTP/1.1 200 OK\r\n"
5926 "Proxy-Connection: keep-alive\r\n"
5927 "Content-Length: 13\r\n\r\n"
5928 "HTTP Response"),
5929 };
Ryan Sleevib8d7ea02018-05-07 20:01:015930 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065931 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5932
5933 MockWrite https_writes[] = {
5934 MockWrite(SYNCHRONOUS,
5935 "GET http://test/https HTTP/1.1\r\n"
5936 "Host: test\r\n"
5937 "Proxy-Connection: keep-alive\r\n\r\n"),
5938 };
5939 MockRead https_reads[] = {
5940 MockRead("HTTP/1.1 200 OK\r\n"
5941 "Proxy-Connection: keep-alive\r\n"
5942 "Content-Length: 14\r\n\r\n"
5943 "HTTPS Response"),
5944 };
Ryan Sleevib8d7ea02018-05-07 20:01:015945 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065946 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5947 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5949
Matt Menkee8648fa2019-01-17 16:47:075950 MockWrite https_trusted_writes[] = {
5951 MockWrite(SYNCHRONOUS,
5952 "GET http://test/https_trusted HTTP/1.1\r\n"
5953 "Host: test\r\n"
5954 "Proxy-Connection: keep-alive\r\n\r\n"),
5955 };
5956 MockRead https_trusted_reads[] = {
5957 MockRead("HTTP/1.1 200 OK\r\n"
5958 "Proxy-Connection: keep-alive\r\n"
5959 "Content-Length: 22\r\n\r\n"
5960 "HTTPS Trusted Response"),
5961 };
5962 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5963 https_trusted_writes);
5964 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5965 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5966 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5967
Matt Menked1eb6d42018-01-17 04:54:065968 struct TestCase {
5969 GURL url;
5970 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075971 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065972 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075973 int expected_idle_socks4_sockets;
5974 int expected_idle_socks5_sockets;
5975 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5976 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065977 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075978 int expected_idle_https_sockets;
5979 // How many idle sockets there should be in the HTTPS proxy socket pool with
5980 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5981 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065982 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075983 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5984 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5985 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5986 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5987 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5988 1},
Matt Menked1eb6d42018-01-17 04:54:065989 };
5990
5991 for (const auto& test_case : kTestCases) {
Titouan Rigoudyba507a882020-07-31 12:15:155992 SCOPED_TRACE(test_case.url);
5993
Matt Menked1eb6d42018-01-17 04:54:065994 HttpRequestInfo request;
5995 request.method = "GET";
5996 request.url = test_case.url;
Ramin Halavatib5e433e2018-02-07 07:41:105997 request.traffic_annotation =
5998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Titouan Rigoudyba507a882020-07-31 12:15:155999 ConnectedHandler connected_handler;
6000
6001 auto transaction = std::make_unique<HttpNetworkTransaction>(
6002 DEFAULT_PRIORITY, session.get());
6003
6004 transaction->SetConnectedCallback(connected_handler.Callback());
6005
Matt Menked1eb6d42018-01-17 04:54:066006 TestCompletionCallback callback;
Titouan Rigoudyba507a882020-07-31 12:15:156007 int rv =
6008 transaction->Start(&request, callback.callback(), NetLogWithSource());
Matt Menked1eb6d42018-01-17 04:54:066009 EXPECT_THAT(callback.GetResult(rv), IsOk());
6010
Titouan Rigoudyba507a882020-07-31 12:15:156011 const HttpResponseInfo* response = transaction->GetResponseInfo();
Matt Menked1eb6d42018-01-17 04:54:066012 ASSERT_TRUE(response);
6013 ASSERT_TRUE(response->headers);
6014 EXPECT_EQ(200, response->headers->response_code());
6015 std::string response_data;
Titouan Rigoudyba507a882020-07-31 12:15:156016 EXPECT_THAT(ReadTransaction(transaction.get(), &response_data), IsOk());
Matt Menked1eb6d42018-01-17 04:54:066017 EXPECT_EQ(test_case.expected_response, response_data);
6018
Titouan Rigoudyba507a882020-07-31 12:15:156019 TransportInfo expected_transport;
6020 expected_transport.type = TransportType::kProxied;
6021 expected_transport.endpoint =
6022 IPEndPoint(IPAddress::IPv4Localhost(),
6023 SameProxyWithDifferentSchemesProxyResolver::kProxyPort);
6024 EXPECT_THAT(connected_handler.transports(),
6025 ElementsAre(expected_transport));
6026
Matt Menked1eb6d42018-01-17 04:54:066027 // Return the socket to the socket pool, so can make sure it's not used for
6028 // the next requests.
Titouan Rigoudyba507a882020-07-31 12:15:156029 transaction.reset();
Matt Menked1eb6d42018-01-17 04:54:066030 base::RunLoop().RunUntilIdle();
6031
6032 // Check the number of idle sockets in the pool, to make sure that used
6033 // sockets are indeed being returned to the socket pool. If each request
6034 // doesn't return an idle socket to the pool, the test would incorrectly
6035 // pass.
Matt Menkee8648fa2019-01-17 16:47:076036 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
6037 session
Matt Menked23ab952019-03-06 00:24:406038 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076039 HttpNetworkSession::NORMAL_SOCKET_POOL,
6040 ProxyServer(ProxyServer::SCHEME_SOCKS4,
6041 SameProxyWithDifferentSchemesProxyResolver::
6042 ProxyHostPortPair()))
6043 ->IdleSocketCount());
6044 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
6045 session
Matt Menked23ab952019-03-06 00:24:406046 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076047 HttpNetworkSession::NORMAL_SOCKET_POOL,
6048 ProxyServer(ProxyServer::SCHEME_SOCKS5,
6049 SameProxyWithDifferentSchemesProxyResolver::
6050 ProxyHostPortPair()))
6051 ->IdleSocketCount());
6052 EXPECT_EQ(test_case.expected_idle_http_sockets,
6053 session
Matt Menked23ab952019-03-06 00:24:406054 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076055 HttpNetworkSession::NORMAL_SOCKET_POOL,
6056 ProxyServer(ProxyServer::SCHEME_HTTP,
6057 SameProxyWithDifferentSchemesProxyResolver::
6058 ProxyHostPortPair()))
6059 ->IdleSocketCount());
6060 EXPECT_EQ(test_case.expected_idle_https_sockets,
6061 session
Matt Menked23ab952019-03-06 00:24:406062 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076063 HttpNetworkSession::NORMAL_SOCKET_POOL,
6064 ProxyServer(ProxyServer::SCHEME_HTTPS,
6065 SameProxyWithDifferentSchemesProxyResolver::
6066 ProxyHostPortPair()))
6067 ->IdleSocketCount());
6068 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
6069 session
Matt Menked23ab952019-03-06 00:24:406070 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076071 HttpNetworkSession::NORMAL_SOCKET_POOL,
6072 ProxyServer(ProxyServer::SCHEME_HTTPS,
6073 SameProxyWithDifferentSchemesProxyResolver::
6074 ProxyHostPortPair(),
6075 true /* is_trusted_proxy */))
6076 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:066077 }
6078}
6079
[email protected]029c83b62013-01-24 05:28:206080// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:016081TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:206082 HttpRequestInfo request1;
6083 request1.method = "GET";
bncce36dca22015-04-21 22:11:236084 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:106085 request1.traffic_annotation =
6086 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206087
6088 HttpRequestInfo request2;
6089 request2.method = "GET";
bncce36dca22015-04-21 22:11:236090 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:106091 request2.traffic_annotation =
6092 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206093
6094 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566095 session_deps_.proxy_resolution_service =
6096 ConfiguredProxyResolutionService::CreateFixed(
6097 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146098 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076099 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096100 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:206101
6102 // Since we have proxy, should try to establish tunnel.
6103 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:176104 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6105 "Host: www.example.org:443\r\n"
6106 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206107
rsleevidb16bb02015-11-12 23:47:176108 MockWrite("GET /1 HTTP/1.1\r\n"
6109 "Host: www.example.org\r\n"
6110 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206111
rsleevidb16bb02015-11-12 23:47:176112 MockWrite("GET /2 HTTP/1.1\r\n"
6113 "Host: www.example.org\r\n"
6114 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206115 };
6116
6117 // The proxy responds to the connect with a 407, using a persistent
6118 // connection.
6119 MockRead data_reads1[] = {
6120 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6121
6122 MockRead("HTTP/1.1 200 OK\r\n"),
6123 MockRead("Content-Length: 1\r\n\r\n"),
6124 MockRead(SYNCHRONOUS, "1"),
6125
6126 MockRead("HTTP/1.1 200 OK\r\n"),
6127 MockRead("Content-Length: 2\r\n\r\n"),
6128 MockRead(SYNCHRONOUS, "22"),
6129 };
6130
Ryan Sleevib8d7ea02018-05-07 20:01:016131 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076132 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:206133 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076134 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:206135
6136 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:586137 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:196138 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206139
6140 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206142
6143 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016144 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206145
6146 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:526147 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:476148 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:526149 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:206150 EXPECT_EQ(1, response1->headers->GetContentLength());
6151
6152 LoadTimingInfo load_timing_info1;
6153 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6154 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
6155
6156 trans1.reset();
6157
6158 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:586159 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196160 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206161
6162 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206164
6165 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016166 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206167
6168 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:526169 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:476170 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:526171 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:206172 EXPECT_EQ(2, response2->headers->GetContentLength());
6173
6174 LoadTimingInfo load_timing_info2;
6175 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6176 TestLoadTimingReused(load_timing_info2);
6177
6178 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6179
6180 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:116181 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:206182}
6183
6184// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:016185TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:206186 HttpRequestInfo request1;
6187 request1.method = "GET";
bncce36dca22015-04-21 22:11:236188 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:106189 request1.traffic_annotation =
6190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206191
6192 HttpRequestInfo request2;
6193 request2.method = "GET";
bncce36dca22015-04-21 22:11:236194 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:106195 request2.traffic_annotation =
6196 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206197
6198 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:596199 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566200 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:496201 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146202 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076203 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:206205
6206 // Since we have proxy, should try to establish tunnel.
6207 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:176208 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6209 "Host: www.example.org:443\r\n"
6210 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206211
rsleevidb16bb02015-11-12 23:47:176212 MockWrite("GET /1 HTTP/1.1\r\n"
6213 "Host: www.example.org\r\n"
6214 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206215
rsleevidb16bb02015-11-12 23:47:176216 MockWrite("GET /2 HTTP/1.1\r\n"
6217 "Host: www.example.org\r\n"
6218 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206219 };
6220
6221 // The proxy responds to the connect with a 407, using a persistent
6222 // connection.
6223 MockRead data_reads1[] = {
6224 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6225
6226 MockRead("HTTP/1.1 200 OK\r\n"),
6227 MockRead("Content-Length: 1\r\n\r\n"),
6228 MockRead(SYNCHRONOUS, "1"),
6229
6230 MockRead("HTTP/1.1 200 OK\r\n"),
6231 MockRead("Content-Length: 2\r\n\r\n"),
6232 MockRead(SYNCHRONOUS, "22"),
6233 };
6234
Ryan Sleevib8d7ea02018-05-07 20:01:016235 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076236 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:206237 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:206239
6240 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:586241 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:196242 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206243
6244 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206246
6247 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016248 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206249
6250 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:526251 ASSERT_TRUE(response1);
6252 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:206253 EXPECT_EQ(1, response1->headers->GetContentLength());
6254
6255 LoadTimingInfo load_timing_info1;
6256 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6257 TestLoadTimingNotReusedWithPac(load_timing_info1,
6258 CONNECT_TIMING_HAS_SSL_TIMES);
6259
6260 trans1.reset();
6261
6262 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:586263 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196264 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206265
6266 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016267 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206268
6269 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016270 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206271
6272 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:526273 ASSERT_TRUE(response2);
6274 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:206275 EXPECT_EQ(2, response2->headers->GetContentLength());
6276
6277 LoadTimingInfo load_timing_info2;
6278 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6279 TestLoadTimingReusedWithPac(load_timing_info2);
6280
6281 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6282
6283 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:116284 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:206285}
6286
Matt Menke8045afd2019-11-14 20:31:196287// Make sure that NetworkIsolationKeys are passed down to the proxy layer.
6288TEST_F(HttpNetworkTransactionTest, ProxyResolvedWithNetworkIsolationKey) {
Matt Menke4807a9a2020-11-21 00:14:416289 const SchemefulSite kSite(GURL("https://foo.test/"));
Matt Menke8045afd2019-11-14 20:31:196290
6291 ProxyConfig proxy_config;
6292 proxy_config.set_auto_detect(true);
6293 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6294
6295 CapturingProxyResolver capturing_proxy_resolver;
6296 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6297 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566298 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke8045afd2019-11-14 20:31:196299 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6300 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6301 std::make_unique<CapturingProxyResolverFactory>(
6302 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096303 nullptr, /*quick_check_enabled=*/true);
Matt Menke8045afd2019-11-14 20:31:196304
6305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6306
6307 // No need to continue with the network request - proxy resolution occurs
6308 // before establishing a data.
6309 StaticSocketDataProvider data{base::span<MockRead>(),
6310 base::span<MockWrite>()};
6311 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
6312 session_deps_.socket_factory->AddSocketDataProvider(&data);
6313
6314 // Run first request until an auth challenge is observed.
6315 HttpRequestInfo request;
6316 request.method = "GET";
6317 request.url = GURL("http://foo.test/");
6318 request.traffic_annotation =
6319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6320 HttpNetworkTransaction trans(LOWEST, session.get());
6321 TestCompletionCallback callback;
6322 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6323 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
6324}
6325
dalyk6d7a8c52019-12-18 21:43:016326// Test that a failure in resolving the proxy hostname is retrievable.
6327TEST_F(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
6328 HttpRequestInfo request;
6329 request.method = "GET";
6330 request.url = GURL("http://www.example.org/");
6331 request.traffic_annotation =
6332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6333
6334 RecordingTestNetLog log;
6335 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566336 session_deps_.proxy_resolution_service =
6337 ConfiguredProxyResolutionService::CreateFixed(
6338 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
dalyk6d7a8c52019-12-18 21:43:016339 MockHostResolver* resolver = new MockHostResolver();
6340 resolver->rules()->AddSimulatedTimeoutFailure("proxy");
6341 session_deps_.net_log = &log;
6342 session_deps_.host_resolver.reset(resolver);
6343 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6344 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6345 TestCompletionCallback callback;
6346
6347 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6348 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6349 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
6350
6351 const HttpResponseInfo* response = trans.GetResponseInfo();
6352 ASSERT_TRUE(response);
6353 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
6354}
6355
[email protected]2df19bb2010-08-25 20:13:466356// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016357TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276358 HttpRequestInfo request;
6359 request.method = "GET";
bncce36dca22015-04-21 22:11:236360 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106361 request.traffic_annotation =
6362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276363
[email protected]2df19bb2010-08-25 20:13:466364 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566365 session_deps_.proxy_resolution_service =
6366 ConfiguredProxyResolutionService::CreateFixed(
6367 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146368 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076369 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466371
[email protected]2df19bb2010-08-25 20:13:466372 // Since we have proxy, should use full url
6373 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236374 MockWrite(
6375 "GET http://www.example.org/ HTTP/1.1\r\n"
6376 "Host: www.example.org\r\n"
6377 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466378 };
6379
6380 MockRead data_reads1[] = {
6381 MockRead("HTTP/1.1 200 OK\r\n"),
6382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6383 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066384 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466385 };
6386
Ryan Sleevib8d7ea02018-05-07 20:01:016387 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076388 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066389 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076390 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466391
Titouan Rigoudyba507a882020-07-31 12:15:156392 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:416393 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466394
bnc691fda62016-08-12 00:43:166395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506396
Titouan Rigoudyba507a882020-07-31 12:15:156397 trans.SetConnectedCallback(connected_handler.Callback());
6398
bnc691fda62016-08-12 00:43:166399 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016400 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466401
6402 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016403 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466404
[email protected]58e32bb2013-01-21 18:23:256405 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166406 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256407 TestLoadTimingNotReused(load_timing_info,
6408 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6409
bnc691fda62016-08-12 00:43:166410 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526411 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466412
tbansal2ecbbc72016-10-06 17:15:476413 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466414 EXPECT_TRUE(response->headers->IsKeepAlive());
6415 EXPECT_EQ(200, response->headers->response_code());
6416 EXPECT_EQ(100, response->headers->GetContentLength());
6417 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6418
Titouan Rigoudyba507a882020-07-31 12:15:156419 TransportInfo expected_transport;
6420 expected_transport.type = TransportType::kProxied;
6421 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6422 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6423
[email protected]2df19bb2010-08-25 20:13:466424 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586425 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466426}
6427
[email protected]7642b5ae2010-09-01 20:55:176428// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016429TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276430 HttpRequestInfo request;
6431 request.method = "GET";
bncce36dca22015-04-21 22:11:236432 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106433 request.traffic_annotation =
6434 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276435
[email protected]7642b5ae2010-09-01 20:55:176436 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566437 session_deps_.proxy_resolution_service =
6438 ConfiguredProxyResolutionService::CreateFixed(
6439 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146440 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076441 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096442 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176443
bncce36dca22015-04-21 22:11:236444 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136445 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456446 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416447 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176448
Ryan Hamilton0239aac2018-05-19 00:03:136449 spdy::SpdySerializedFrame resp(
6450 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6451 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176452 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416453 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176454 };
6455
Ryan Sleevib8d7ea02018-05-07 20:01:016456 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076457 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176458
[email protected]8ddf8322012-02-23 18:08:066459 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366460 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176462
Titouan Rigoudyba507a882020-07-31 12:15:156463 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:416464 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176465
bnc691fda62016-08-12 00:43:166466 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506467
Titouan Rigoudyba507a882020-07-31 12:15:156468 trans.SetConnectedCallback(connected_handler.Callback());
6469
bnc691fda62016-08-12 00:43:166470 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016471 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176472
6473 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016474 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176475
[email protected]58e32bb2013-01-21 18:23:256476 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166477 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256478 TestLoadTimingNotReused(load_timing_info,
6479 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6480
bnc691fda62016-08-12 00:43:166481 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526482 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476483 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526484 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026485 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176486
Titouan Rigoudyba507a882020-07-31 12:15:156487 TransportInfo expected_transport;
6488 expected_transport.type = TransportType::kProxied;
6489 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6490 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6491
[email protected]7642b5ae2010-09-01 20:55:176492 std::string response_data;
bnc691fda62016-08-12 00:43:166493 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236494 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176495}
6496
[email protected]1c173852014-06-19 12:51:506497// Verifies that a session which races and wins against the owning transaction
6498// (completing prior to host resolution), doesn't fail the transaction.
6499// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016500TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506501 HttpRequestInfo request;
6502 request.method = "GET";
bncce36dca22015-04-21 22:11:236503 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106504 request.traffic_annotation =
6505 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506506
6507 // Configure SPDY proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566508 session_deps_.proxy_resolution_service =
6509 ConfiguredProxyResolutionService::CreateFixed(
6510 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146511 RecordingBoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506512 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096513 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506514
bncce36dca22015-04-21 22:11:236515 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136516 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456517 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416518 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506519
Raul Tambre94493c652019-03-11 17:18:356520 spdy::SpdySerializedFrame resp(
6521 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136522 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506523 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416524 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506525 };
6526
Ryan Sleevib8d7ea02018-05-07 20:01:016527 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506528 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6529
6530 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366531 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6533
6534 TestCompletionCallback callback1;
6535
bnc691fda62016-08-12 00:43:166536 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506537
6538 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506539 session_deps_.host_resolver->set_ondemand_mode(true);
6540
bnc691fda62016-08-12 00:43:166541 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016542 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506543
6544 // Race a session to the proxy, which completes first.
6545 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046546 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116547 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346548 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6549 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506550 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526551 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506552
6553 // Unstall the resolution begun by the transaction.
6554 session_deps_.host_resolver->set_ondemand_mode(true);
6555 session_deps_.host_resolver->ResolveAllPending();
6556
6557 EXPECT_FALSE(callback1.have_result());
6558 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016559 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506560
bnc691fda62016-08-12 00:43:166561 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526562 ASSERT_TRUE(response);
6563 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026564 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506565
6566 std::string response_data;
bnc691fda62016-08-12 00:43:166567 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506568 EXPECT_EQ(kUploadData, response_data);
6569}
6570
[email protected]dc7bd1c52010-11-12 00:01:136571// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016572TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276573 HttpRequestInfo request;
6574 request.method = "GET";
bncce36dca22015-04-21 22:11:236575 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106576 request.traffic_annotation =
6577 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276578
[email protected]79cb5c12011-09-12 13:12:046579 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566580 session_deps_.proxy_resolution_service =
6581 ConfiguredProxyResolutionService::CreateFixed(
6582 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146583 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076584 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096585 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136586
[email protected]dc7bd1c52010-11-12 00:01:136587 // The first request will be a bare GET, the second request will be a
6588 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456589 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136590 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486591 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386592 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136593 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466594 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136595 };
Ryan Hamilton0239aac2018-05-19 00:03:136596 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246597 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486598 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136599 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416600 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136601 };
6602
6603 // The first response is a 407 proxy authentication challenge, and the second
6604 // response will be a 200 response since the second request includes a valid
6605 // Authorization header.
6606 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466607 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136608 };
Ryan Hamilton0239aac2018-05-19 00:03:136609 spdy::SpdySerializedFrame resp_authentication(
6610 spdy_util_.ConstructSpdyReplyError(
6611 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246612 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136613 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416614 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136615 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356616 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136617 spdy::SpdySerializedFrame body_data(
6618 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136619 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416620 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466621 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416622 CreateMockRead(resp_data, 4),
6623 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136624 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136625 };
6626
Ryan Sleevib8d7ea02018-05-07 20:01:016627 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076628 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136629
[email protected]8ddf8322012-02-23 18:08:066630 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366631 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076632 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136633
[email protected]49639fa2011-12-20 23:22:416634 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136635
bnc691fda62016-08-12 00:43:166636 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136637
bnc691fda62016-08-12 00:43:166638 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136640
6641 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016642 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136643
bnc691fda62016-08-12 00:43:166644 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136645
wezca1070932016-05-26 20:30:526646 ASSERT_TRUE(response);
6647 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136648 EXPECT_EQ(407, response->headers->response_code());
6649 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586650 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136651
[email protected]49639fa2011-12-20 23:22:416652 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136653
bnc691fda62016-08-12 00:43:166654 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016655 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136656
6657 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016658 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136659
bnc691fda62016-08-12 00:43:166660 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136661
wezca1070932016-05-26 20:30:526662 ASSERT_TRUE(response_restart);
6663 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136664 EXPECT_EQ(200, response_restart->headers->response_code());
6665 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586666 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136667}
6668
[email protected]d9da5fe2010-10-13 22:37:166669// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016670TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276671 HttpRequestInfo request;
6672 request.method = "GET";
bncce36dca22015-04-21 22:11:236673 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106674 request.traffic_annotation =
6675 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276676
[email protected]d9da5fe2010-10-13 22:37:166677 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566678 session_deps_.proxy_resolution_service =
6679 ConfiguredProxyResolutionService::CreateFixed(
6680 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146681 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076682 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096683 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166684
bnc691fda62016-08-12 00:43:166685 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166686
bncce36dca22015-04-21 22:11:236687 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136688 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046689 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6690 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236691 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166692
bncce36dca22015-04-21 22:11:236693 const char get[] =
6694 "GET / HTTP/1.1\r\n"
6695 "Host: www.example.org\r\n"
6696 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136697 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196698 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136699 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356700 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166701 const char resp[] = "HTTP/1.1 200 OK\r\n"
6702 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136703 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196704 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136705 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196706 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136707 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416708 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046709
6710 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416711 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6712 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046713 };
6714
[email protected]d9da5fe2010-10-13 22:37:166715 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416716 CreateMockRead(conn_resp, 1, ASYNC),
6717 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6718 CreateMockRead(wrapped_body, 4, ASYNC),
6719 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136720 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166721 };
6722
Ryan Sleevib8d7ea02018-05-07 20:01:016723 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076724 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166725
[email protected]8ddf8322012-02-23 18:08:066726 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366727 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076728 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066729 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076730 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166731
[email protected]49639fa2011-12-20 23:22:416732 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166733
bnc691fda62016-08-12 00:43:166734 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016735 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166736
6737 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016738 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166739
[email protected]58e32bb2013-01-21 18:23:256740 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166741 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256742 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6743
bnc691fda62016-08-12 00:43:166744 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526745 ASSERT_TRUE(response);
6746 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166747 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6748
6749 std::string response_data;
bnc691fda62016-08-12 00:43:166750 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166751 EXPECT_EQ("1234567890", response_data);
6752}
6753
6754// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016755TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6756 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386757
[email protected]cb9bf6ca2011-01-28 13:15:276758 HttpRequestInfo request;
6759 request.method = "GET";
bncce36dca22015-04-21 22:11:236760 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106761 request.traffic_annotation =
6762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276763
[email protected]d9da5fe2010-10-13 22:37:166764 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566765 session_deps_.proxy_resolution_service =
6766 ConfiguredProxyResolutionService::CreateFixed(
6767 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146768 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076769 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166771
bnc691fda62016-08-12 00:43:166772 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166773
bncce36dca22015-04-21 22:11:236774 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136775 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046776 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6777 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236778 // fetch https://www.example.org/ via SPDY
6779 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136780 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496781 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136782 spdy::SpdySerializedFrame wrapped_get(
6783 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6784 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356785 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136786 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356787 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136788 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026789 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136790 spdy::SpdySerializedFrame body(
6791 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6792 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026793 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136794 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416795 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136796 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416797 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046798
6799 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416800 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6801 CreateMockWrite(window_update_get_resp, 6),
6802 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046803 };
6804
[email protected]d9da5fe2010-10-13 22:37:166805 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416806 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096807 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416808 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6809 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136810 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166811 };
6812
Ryan Sleevib8d7ea02018-05-07 20:01:016813 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076814 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166815
[email protected]8ddf8322012-02-23 18:08:066816 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366817 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066819 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366820 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076821 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166822
[email protected]49639fa2011-12-20 23:22:416823 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166824
bnc691fda62016-08-12 00:43:166825 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016826 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166827
rch32320842015-05-16 15:57:096828 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556829 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096830 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596831 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166832 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016833 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166834
[email protected]58e32bb2013-01-21 18:23:256835 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166836 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256837 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6838
bnc691fda62016-08-12 00:43:166839 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526840 ASSERT_TRUE(response);
6841 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026842 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166843
6844 std::string response_data;
bnc691fda62016-08-12 00:43:166845 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236846 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166847}
6848
6849// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016850TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276851 HttpRequestInfo request;
6852 request.method = "GET";
bncce36dca22015-04-21 22:11:236853 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106854 request.traffic_annotation =
6855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276856
[email protected]d9da5fe2010-10-13 22:37:166857 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566858 session_deps_.proxy_resolution_service =
6859 ConfiguredProxyResolutionService::CreateFixed(
6860 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146861 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076862 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096863 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166864
bnc691fda62016-08-12 00:43:166865 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166866
bncce36dca22015-04-21 22:11:236867 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136868 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046869 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6870 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136871 spdy::SpdySerializedFrame get(
6872 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166873
6874 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416875 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166876 };
6877
Ryan Hamilton0239aac2018-05-19 00:03:136878 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6879 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166880 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416881 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166882 };
6883
Ryan Sleevib8d7ea02018-05-07 20:01:016884 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076885 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166886
[email protected]8ddf8322012-02-23 18:08:066887 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366888 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066890 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366891 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076892 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166893
[email protected]49639fa2011-12-20 23:22:416894 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166895
bnc691fda62016-08-12 00:43:166896 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016897 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166898
6899 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016900 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166901
ttuttle960fcbf2016-04-19 13:26:326902 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166903}
6904
Matt Menkecb2cd0982018-12-19 17:54:046905// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246906// is observed, but does exist by the time auth credentials are provided. In
6907// this case, auth and SSL are fully negotated on the second request, but then
6908// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046909TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6910 ProxyConfig proxy_config;
6911 proxy_config.set_auto_detect(true);
6912 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6913
6914 CapturingProxyResolver capturing_proxy_resolver;
6915 capturing_proxy_resolver.set_proxy_server(
6916 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6917 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566918 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menkecb2cd0982018-12-19 17:54:046919 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6920 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6921 std::make_unique<CapturingProxyResolverFactory>(
6922 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096923 nullptr, /*quick_check_enabled=*/true);
Matt Menkecb2cd0982018-12-19 17:54:046924
6925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6926
6927 const char kMyUrl[] = "https://www.example.org/";
6928 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6929 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356930 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046931 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6932
6933 spdy_util_.UpdateWithStreamDestruction(1);
6934 spdy::SpdySerializedFrame get2(
6935 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6936 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356937 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046938 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6939
6940 MockWrite auth_challenge_writes[] = {
6941 MockWrite(ASYNC, 0,
6942 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6943 "Host: www.example.org:443\r\n"
6944 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246945 MockWrite(ASYNC, 2,
6946 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6947 "Host: www.example.org:443\r\n"
6948 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046949 };
6950
6951 MockRead auth_challenge_reads[] = {
6952 MockRead(ASYNC, 1,
6953 "HTTP/1.1 407 Authentication Required\r\n"
6954 "Content-Length: 0\r\n"
6955 "Proxy-Connection: close\r\n"
6956 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6957 };
6958
6959 MockWrite spdy_writes[] = {
6960 MockWrite(ASYNC, 0,
6961 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6962 "Host: www.example.org:443\r\n"
6963 "Proxy-Connection: keep-alive\r\n"
6964 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6965 CreateMockWrite(get, 2),
6966 CreateMockWrite(get2, 5),
6967 };
6968
6969 MockRead spdy_reads[] = {
6970 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6971 CreateMockRead(get_resp, 3, ASYNC),
6972 CreateMockRead(body, 4, ASYNC),
6973 CreateMockRead(get_resp2, 6, ASYNC),
6974 CreateMockRead(body2, 7, ASYNC),
6975
6976 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6977 };
6978
Matt Menke5062be22019-05-01 17:50:246979 MockWrite auth_response_writes_discarded_socket[] = {
6980 MockWrite(ASYNC, 0,
6981 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6982 "Host: www.example.org:443\r\n"
6983 "Proxy-Connection: keep-alive\r\n"
6984 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6985 };
6986
6987 MockRead auth_response_reads_discarded_socket[] = {
6988 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6989 };
6990
Matt Menkecb2cd0982018-12-19 17:54:046991 SequencedSocketData auth_challenge1(auth_challenge_reads,
6992 auth_challenge_writes);
6993 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6994
6995 SequencedSocketData auth_challenge2(auth_challenge_reads,
6996 auth_challenge_writes);
6997 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6998
6999 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7000 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7001
Matt Menke5062be22019-05-01 17:50:247002 SequencedSocketData auth_response_discarded_socket(
7003 auth_response_reads_discarded_socket,
7004 auth_response_writes_discarded_socket);
7005 session_deps_.socket_factory->AddSocketDataProvider(
7006 &auth_response_discarded_socket);
7007
Matt Menkecb2cd0982018-12-19 17:54:047008 SSLSocketDataProvider ssl(ASYNC, OK);
7009 ssl.next_proto = kProtoHTTP2;
7010 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7011
Matt Menke5062be22019-05-01 17:50:247012 SSLSocketDataProvider ssl2(ASYNC, OK);
7013 ssl2.next_proto = kProtoHTTP2;
7014 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7015
Matt Menkecb2cd0982018-12-19 17:54:047016 TestCompletionCallback callback;
7017 std::string response_data;
7018
7019 // Run first request until an auth challenge is observed.
7020 HttpRequestInfo request1;
7021 request1.method = "GET";
7022 request1.url = GURL(kMyUrl);
7023 request1.traffic_annotation =
7024 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7025 HttpNetworkTransaction trans1(LOWEST, session.get());
7026 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7027 EXPECT_THAT(callback.GetResult(rv), IsOk());
7028 const HttpResponseInfo* response = trans1.GetResponseInfo();
7029 ASSERT_TRUE(response);
7030 ASSERT_TRUE(response->headers);
7031 EXPECT_EQ(407, response->headers->response_code());
7032 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587033 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:047034
7035 // Run second request until an auth challenge is observed.
7036 HttpRequestInfo request2;
7037 request2.method = "GET";
7038 request2.url = GURL(kMyUrl);
7039 request2.traffic_annotation =
7040 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7041 HttpNetworkTransaction trans2(LOWEST, session.get());
7042 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7043 EXPECT_THAT(callback.GetResult(rv), IsOk());
7044 response = trans2.GetResponseInfo();
7045 ASSERT_TRUE(response);
7046 ASSERT_TRUE(response->headers);
7047 EXPECT_EQ(407, response->headers->response_code());
7048 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587049 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:047050
7051 // Now provide credentials for the first request, and wait for it to complete.
7052 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
7053 rv = callback.GetResult(rv);
7054 EXPECT_THAT(rv, IsOk());
7055 response = trans1.GetResponseInfo();
7056 ASSERT_TRUE(response);
7057 ASSERT_TRUE(response->headers);
7058 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7059 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7060 EXPECT_EQ(kUploadData, response_data);
7061
7062 // Now provide credentials for the second request. It should notice the
7063 // existing session, and reuse it.
7064 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
7065 EXPECT_THAT(callback.GetResult(rv), IsOk());
7066 response = trans2.GetResponseInfo();
7067 ASSERT_TRUE(response);
7068 ASSERT_TRUE(response->headers);
7069 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7070 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7071 EXPECT_EQ(kUploadData, response_data);
7072}
7073
[email protected]f6c63db52013-02-02 00:35:227074// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
7075// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:017076TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:227077 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
7078 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567079 session_deps_.proxy_resolution_service =
7080 ConfiguredProxyResolutionService::CreateFixed(
7081 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147082 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077083 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097084 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507085 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227086
7087 HttpRequestInfo request1;
7088 request1.method = "GET";
bncce36dca22015-04-21 22:11:237089 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227090 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107091 request1.traffic_annotation =
7092 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227093
7094 HttpRequestInfo request2;
7095 request2.method = "GET";
bncce36dca22015-04-21 22:11:237096 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227097 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107098 request2.traffic_annotation =
7099 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227100
bncce36dca22015-04-21 22:11:237101 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:137102 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047103 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7104 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:137105 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:357106 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:227107
bncce36dca22015-04-21 22:11:237108 // Fetch https://www.example.org/ via HTTP.
7109 const char get1[] =
7110 "GET / HTTP/1.1\r\n"
7111 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227112 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137113 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:197114 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:227115 const char resp1[] = "HTTP/1.1 200 OK\r\n"
7116 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137117 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:197118 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:137119 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:197120 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:137121 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:417122 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:227123
bncce36dca22015-04-21 22:11:237124 // CONNECT to mail.example.org:443 via SPDY.
Bence Béky4c325e52020-10-22 20:48:017125 spdy::Http2HeaderBlock connect2_block;
Ryan Hamilton0239aac2018-05-19 00:03:137126 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
7127 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
7128 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:047129 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
7130 false));
[email protected]601e03f12014-04-06 16:26:397131
Ryan Hamilton0239aac2018-05-19 00:03:137132 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:357133 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:227134
bncce36dca22015-04-21 22:11:237135 // Fetch https://mail.example.org/ via HTTP.
7136 const char get2[] =
7137 "GET / HTTP/1.1\r\n"
7138 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227139 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137140 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:197141 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:227142 const char resp2[] = "HTTP/1.1 200 OK\r\n"
7143 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137144 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:197145 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:137146 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:197147 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:227148
7149 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417150 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
7151 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:227152 };
7153
7154 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417155 CreateMockRead(conn_resp1, 1, ASYNC),
7156 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
7157 CreateMockRead(wrapped_body1, 4, ASYNC),
7158 CreateMockRead(conn_resp2, 6, ASYNC),
7159 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
7160 CreateMockRead(wrapped_body2, 9, ASYNC),
7161 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:227162 };
7163
Ryan Sleevib8d7ea02018-05-07 20:01:017164 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507165 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227166
7167 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367168 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507169 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227170 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:227172 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507173 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:227174
7175 TestCompletionCallback callback;
7176
bnc691fda62016-08-12 00:43:167177 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207178 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017179 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227180
7181 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167182 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:227183 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7184
bnc691fda62016-08-12 00:43:167185 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527186 ASSERT_TRUE(response);
7187 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227188 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7189
7190 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447191 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:167192 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507193 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227194
bnc691fda62016-08-12 00:43:167195 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207196 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017197 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227198
7199 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167200 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227201 // Even though the SPDY connection is reused, a new tunnelled connection has
7202 // to be created, so the socket's load timing looks like a fresh connection.
7203 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
7204
7205 // The requests should have different IDs, since they each are using their own
7206 // separate stream.
7207 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7208
bnc691fda62016-08-12 00:43:167209 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507210 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227211}
7212
7213// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
7214// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:017215TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:227216 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
7217 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567218 session_deps_.proxy_resolution_service =
7219 ConfiguredProxyResolutionService::CreateFixed(
7220 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147221 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077222 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097223 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507224 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227225
7226 HttpRequestInfo request1;
7227 request1.method = "GET";
bncce36dca22015-04-21 22:11:237228 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227229 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107230 request1.traffic_annotation =
7231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227232
7233 HttpRequestInfo request2;
7234 request2.method = "GET";
bncce36dca22015-04-21 22:11:237235 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:227236 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107237 request2.traffic_annotation =
7238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227239
bncce36dca22015-04-21 22:11:237240 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:137241 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047242 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7243 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:137244 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:357245 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:227246
bncce36dca22015-04-21 22:11:237247 // Fetch https://www.example.org/ via HTTP.
7248 const char get1[] =
7249 "GET / HTTP/1.1\r\n"
7250 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227251 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137252 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:197253 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:227254 const char resp1[] = "HTTP/1.1 200 OK\r\n"
7255 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137256 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:197257 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:137258 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:197259 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:137260 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:417261 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:227262
bncce36dca22015-04-21 22:11:237263 // Fetch https://www.example.org/2 via HTTP.
7264 const char get2[] =
7265 "GET /2 HTTP/1.1\r\n"
7266 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227267 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137268 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:197269 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:227270 const char resp2[] = "HTTP/1.1 200 OK\r\n"
7271 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137272 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:197273 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:137274 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:197275 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:227276
7277 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417278 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
7279 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:227280 };
7281
7282 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417283 CreateMockRead(conn_resp1, 1, ASYNC),
7284 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:467285 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417286 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:467287 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417288 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:227289 };
7290
Ryan Sleevib8d7ea02018-05-07 20:01:017291 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507292 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227293
7294 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367295 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507296 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227297 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:227299
7300 TestCompletionCallback callback;
7301
bnc87dcefc2017-05-25 12:47:587302 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197303 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207304 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017305 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227306
7307 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017308 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227309
7310 LoadTimingInfo load_timing_info;
7311 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7312 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7313
7314 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527315 ASSERT_TRUE(response);
7316 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227317 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7318
7319 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447320 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:507321 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227322 trans.reset();
7323
bnc87dcefc2017-05-25 12:47:587324 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:197325 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207326 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017327 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227328
[email protected]f6c63db52013-02-02 00:35:227329 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017330 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227331
7332 LoadTimingInfo load_timing_info2;
7333 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
7334 TestLoadTimingReused(load_timing_info2);
7335
7336 // The requests should have the same ID.
7337 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7338
[email protected]90499482013-06-01 00:39:507339 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227340}
7341
7342// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
7343// Proxy to different servers.
bncd16676a2016-07-20 16:23:017344TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:227345 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567346 session_deps_.proxy_resolution_service =
7347 ConfiguredProxyResolutionService::CreateFixed(
7348 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147349 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077350 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097351 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507352 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227353
7354 HttpRequestInfo request1;
7355 request1.method = "GET";
bncce36dca22015-04-21 22:11:237356 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227357 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107358 request1.traffic_annotation =
7359 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227360
7361 HttpRequestInfo request2;
7362 request2.method = "GET";
bncce36dca22015-04-21 22:11:237363 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227364 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107365 request2.traffic_annotation =
7366 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227367
bncce36dca22015-04-21 22:11:237368 // http://www.example.org/
Bence Béky4c325e52020-10-22 20:48:017369 spdy::Http2HeaderBlock headers(
bncce36dca22015-04-21 22:11:237370 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137371 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:157372 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137373 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:357374 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:137375 spdy::SpdySerializedFrame body1(
7376 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:387377 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:227378
bncce36dca22015-04-21 22:11:237379 // http://mail.example.org/
Bence Béky4c325e52020-10-22 20:48:017380 spdy::Http2HeaderBlock headers2(
bncce36dca22015-04-21 22:11:237381 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137382 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:157383 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137384 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357385 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137386 spdy::SpdySerializedFrame body2(
7387 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227388
7389 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417390 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227391 };
7392
7393 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417394 CreateMockRead(get_resp1, 1, ASYNC),
7395 CreateMockRead(body1, 2, ASYNC),
7396 CreateMockRead(get_resp2, 4, ASYNC),
7397 CreateMockRead(body2, 5, ASYNC),
7398 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227399 };
7400
Ryan Sleevib8d7ea02018-05-07 20:01:017401 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507402 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227403
7404 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367405 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227407
7408 TestCompletionCallback callback;
7409
bnc87dcefc2017-05-25 12:47:587410 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197411 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207412 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017413 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227414
7415 LoadTimingInfo load_timing_info;
7416 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7417 TestLoadTimingNotReused(load_timing_info,
7418 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7419
7420 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527421 ASSERT_TRUE(response);
7422 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027423 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227424
7425 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447426 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507427 rv = trans->Read(buf.get(), 256, callback.callback());
7428 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227429 // Delete the first request, so the second one can reuse the socket.
7430 trans.reset();
7431
bnc691fda62016-08-12 00:43:167432 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207433 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017434 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227435
7436 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167437 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227438 TestLoadTimingReused(load_timing_info2);
7439
7440 // The requests should have the same ID.
7441 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7442
bnc691fda62016-08-12 00:43:167443 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507444 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227445}
7446
Matt Menke2436b2f2018-12-11 18:07:117447// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7448// direct (non-proxied) request to the proxy server are not pooled, as that
7449// would break socket pool isolation.
7450TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7451 ProxyConfig proxy_config;
7452 proxy_config.set_auto_detect(true);
7453 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7454
7455 CapturingProxyResolver capturing_proxy_resolver;
7456 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567457 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117458 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7459 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7460 std::make_unique<CapturingProxyResolverFactory>(
7461 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097462 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117463
7464 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7465
7466 SpdyTestUtil spdy_util1;
7467 // CONNECT to www.example.org:443 via HTTP/2.
7468 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047469 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7470 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117471 // fetch https://www.example.org/ via HTTP/2.
7472 const char kMyUrl[] = "https://www.example.org/";
7473 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7474 spdy::SpdySerializedFrame wrapped_get(
7475 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7476 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357477 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117478 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357479 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117480 spdy::SpdySerializedFrame wrapped_get_resp(
7481 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7482 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7483 spdy::SpdySerializedFrame wrapped_body(
7484 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7485 spdy::SpdySerializedFrame window_update_get_resp(
7486 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7487 spdy::SpdySerializedFrame window_update_body(
7488 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7489
7490 MockWrite spdy_writes1[] = {
7491 CreateMockWrite(connect, 0),
7492 CreateMockWrite(wrapped_get, 2),
7493 CreateMockWrite(window_update_get_resp, 6),
7494 CreateMockWrite(window_update_body, 7),
7495 };
7496
7497 MockRead spdy_reads1[] = {
7498 CreateMockRead(conn_resp, 1, ASYNC),
7499 MockRead(ASYNC, ERR_IO_PENDING, 3),
7500 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7501 CreateMockRead(wrapped_body, 5, ASYNC),
7502 MockRead(ASYNC, 0, 8),
7503 };
7504
7505 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7506 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7507
7508 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7509 // a new pipe.
7510 SpdyTestUtil spdy_util2;
7511 spdy::SpdySerializedFrame req(
7512 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7513 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7514
7515 spdy::SpdySerializedFrame resp(
7516 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7517 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7518 MockRead spdy_reads2[] = {
7519 CreateMockRead(resp, 1),
7520 CreateMockRead(data, 2),
7521 MockRead(ASYNC, 0, 3),
7522 };
7523 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7524 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7525
7526 SSLSocketDataProvider ssl(ASYNC, OK);
7527 ssl.next_proto = kProtoHTTP2;
7528 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7529 SSLSocketDataProvider ssl2(ASYNC, OK);
7530 ssl2.next_proto = kProtoHTTP2;
7531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7532 SSLSocketDataProvider ssl3(ASYNC, OK);
7533 ssl3.next_proto = kProtoHTTP2;
7534 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7535
7536 TestCompletionCallback callback;
7537 std::string response_data;
7538
7539 // Make a request using proxy:70 as a HTTP/2 proxy.
7540 capturing_proxy_resolver.set_proxy_server(
7541 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7542 HttpRequestInfo request1;
7543 request1.method = "GET";
7544 request1.url = GURL("https://www.example.org/");
7545 request1.traffic_annotation =
7546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7547
7548 HttpNetworkTransaction trans1(LOWEST, session.get());
7549 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7551
7552 // Allow the SpdyProxyClientSocket's write callback to complete.
7553 base::RunLoop().RunUntilIdle();
7554 // Now allow the read of the response to complete.
7555 spdy_data1.Resume();
7556 rv = callback.WaitForResult();
7557 EXPECT_THAT(rv, IsOk());
7558
7559 const HttpResponseInfo* response = trans1.GetResponseInfo();
7560 ASSERT_TRUE(response);
7561 ASSERT_TRUE(response->headers);
7562 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7563
7564 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7565 EXPECT_EQ(kUploadData, response_data);
7566 RunUntilIdle();
7567
7568 // Make a direct HTTP/2 request to proxy:70.
7569 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7570 HttpRequestInfo request2;
7571 request2.method = "GET";
7572 request2.url = GURL("https://proxy:70/");
7573 request2.traffic_annotation =
7574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7575 HttpNetworkTransaction trans2(LOWEST, session.get());
7576 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7577 NetLogWithSource())),
7578 IsOk());
7579 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7580}
7581
7582// Same as above, but reverse request order, since the code to check for an
7583// existing session is different for tunnels and direct connections.
7584TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7585 // Configure against https proxy server "myproxy:80".
7586 ProxyConfig proxy_config;
7587 proxy_config.set_auto_detect(true);
7588 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7589
7590 CapturingProxyResolver capturing_proxy_resolver;
7591 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567592 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117593 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7594 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7595 std::make_unique<CapturingProxyResolverFactory>(
7596 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097597 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117598
7599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7600 // Fetch https://proxy:70/ via HTTP/2.
7601 SpdyTestUtil spdy_util1;
7602 spdy::SpdySerializedFrame req(
7603 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7604 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7605
7606 spdy::SpdySerializedFrame resp(
7607 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7608 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7609 MockRead spdy_reads1[] = {
7610 CreateMockRead(resp, 1),
7611 CreateMockRead(data, 2),
7612 MockRead(ASYNC, 0, 3),
7613 };
7614 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7615 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7616
7617 SpdyTestUtil spdy_util2;
7618 // CONNECT to www.example.org:443 via HTTP/2.
7619 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047620 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7621 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117622 // fetch https://www.example.org/ via HTTP/2.
7623 const char kMyUrl[] = "https://www.example.org/";
7624 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7625 spdy::SpdySerializedFrame wrapped_get(
7626 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7627 spdy::SpdySerializedFrame conn_resp(
7628 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7629 spdy::SpdySerializedFrame get_resp(
7630 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7631 spdy::SpdySerializedFrame wrapped_get_resp(
7632 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7633 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7634 spdy::SpdySerializedFrame wrapped_body(
7635 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7636 spdy::SpdySerializedFrame window_update_get_resp(
7637 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7638 spdy::SpdySerializedFrame window_update_body(
7639 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7640
7641 MockWrite spdy_writes2[] = {
7642 CreateMockWrite(connect, 0),
7643 CreateMockWrite(wrapped_get, 2),
7644 CreateMockWrite(window_update_get_resp, 6),
7645 CreateMockWrite(window_update_body, 7),
7646 };
7647
7648 MockRead spdy_reads2[] = {
7649 CreateMockRead(conn_resp, 1, ASYNC),
7650 MockRead(ASYNC, ERR_IO_PENDING, 3),
7651 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7652 CreateMockRead(wrapped_body, 5, ASYNC),
7653 MockRead(ASYNC, 0, 8),
7654 };
7655
7656 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7657 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7658
7659 SSLSocketDataProvider ssl(ASYNC, OK);
7660 ssl.next_proto = kProtoHTTP2;
7661 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7662 SSLSocketDataProvider ssl2(ASYNC, OK);
7663 ssl2.next_proto = kProtoHTTP2;
7664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7665 SSLSocketDataProvider ssl3(ASYNC, OK);
7666 ssl3.next_proto = kProtoHTTP2;
7667 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7668
7669 TestCompletionCallback callback;
7670 std::string response_data;
7671
7672 // Make a direct HTTP/2 request to proxy:70.
7673 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7674 HttpRequestInfo request1;
7675 request1.method = "GET";
7676 request1.url = GURL("https://proxy:70/");
7677 request1.traffic_annotation =
7678 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7679 HttpNetworkTransaction trans1(LOWEST, session.get());
7680 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7681 NetLogWithSource())),
7682 IsOk());
7683 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7684 RunUntilIdle();
7685
7686 // Make a request using proxy:70 as a HTTP/2 proxy.
7687 capturing_proxy_resolver.set_proxy_server(
7688 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7689 HttpRequestInfo request2;
7690 request2.method = "GET";
7691 request2.url = GURL("https://www.example.org/");
7692 request2.traffic_annotation =
7693 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7694
7695 HttpNetworkTransaction trans2(LOWEST, session.get());
7696 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7697 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7698
7699 // Allow the SpdyProxyClientSocket's write callback to complete.
7700 base::RunLoop().RunUntilIdle();
7701 // Now allow the read of the response to complete.
7702 spdy_data2.Resume();
7703 rv = callback.WaitForResult();
7704 EXPECT_THAT(rv, IsOk());
7705
7706 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7707 ASSERT_TRUE(response2);
7708 ASSERT_TRUE(response2->headers);
7709 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7710
7711 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7712 EXPECT_EQ(kUploadData, response_data);
7713}
7714
[email protected]2df19bb2010-08-25 20:13:467715// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017716TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467717 HttpRequestInfo request;
7718 request.method = "GET";
bncce36dca22015-04-21 22:11:237719 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467720 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:007721 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:107722 request.traffic_annotation =
7723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467724
[email protected]79cb5c12011-09-12 13:12:047725 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567726 session_deps_.proxy_resolution_service =
7727 ConfiguredProxyResolutionService::CreateFixed(
7728 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147729 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077730 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097731 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277732
[email protected]2df19bb2010-08-25 20:13:467733 // Since we have proxy, should use full url
7734 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167735 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7736 "Host: www.example.org\r\n"
7737 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467738
bnc691fda62016-08-12 00:43:167739 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237740 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167741 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7742 "Host: www.example.org\r\n"
7743 "Proxy-Connection: keep-alive\r\n"
7744 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467745 };
7746
7747 // The proxy responds to the GET with a 407, using a persistent
7748 // connection.
7749 MockRead data_reads1[] = {
7750 // No credentials.
7751 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7752 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7753 MockRead("Proxy-Connection: keep-alive\r\n"),
7754 MockRead("Content-Length: 0\r\n\r\n"),
7755
7756 MockRead("HTTP/1.1 200 OK\r\n"),
7757 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7758 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067759 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467760 };
7761
Ryan Sleevib8d7ea02018-05-07 20:01:017762 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077763 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067764 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077765 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467766
[email protected]49639fa2011-12-20 23:22:417767 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467768
bnc691fda62016-08-12 00:43:167769 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507770
bnc691fda62016-08-12 00:43:167771 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017772 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467773
7774 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017775 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467776
[email protected]58e32bb2013-01-21 18:23:257777 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167778 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257779 TestLoadTimingNotReused(load_timing_info,
7780 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7781
bnc691fda62016-08-12 00:43:167782 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527783 ASSERT_TRUE(response);
7784 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467785 EXPECT_EQ(407, response->headers->response_code());
7786 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587787 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507788 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467789
[email protected]49639fa2011-12-20 23:22:417790 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467791
bnc691fda62016-08-12 00:43:167792 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467794
7795 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017796 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467797
[email protected]58e32bb2013-01-21 18:23:257798 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167799 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257800 // Retrying with HTTP AUTH is considered to be reusing a socket.
7801 TestLoadTimingReused(load_timing_info);
7802
bnc691fda62016-08-12 00:43:167803 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527804 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467805
7806 EXPECT_TRUE(response->headers->IsKeepAlive());
7807 EXPECT_EQ(200, response->headers->response_code());
7808 EXPECT_EQ(100, response->headers->GetContentLength());
7809 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507810 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467811
7812 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587813 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467814}
7815
[email protected]23e482282013-06-14 16:08:027816void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087817 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427818 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087819 request.method = "GET";
bncce36dca22015-04-21 22:11:237820 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107821 request.traffic_annotation =
7822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087823
[email protected]cb9bf6ca2011-01-28 13:15:277824 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567825 session_deps_.proxy_resolution_service =
7826 ConfiguredProxyResolutionService::CreateFixed(
7827 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097828 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277829
[email protected]c744cf22009-02-27 07:28:087830 // Since we have proxy, should try to establish tunnel.
7831 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177832 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7833 "Host: www.example.org:443\r\n"
7834 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087835 };
7836
7837 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237838 status, MockRead("Content-Length: 10\r\n\r\n"),
7839 // No response body because the test stops reading here.
7840 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087841 };
7842
Ryan Sleevib8d7ea02018-05-07 20:01:017843 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077844 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087845
[email protected]49639fa2011-12-20 23:22:417846 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087847
bnc691fda62016-08-12 00:43:167848 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507849
tfarina42834112016-09-22 13:38:207850 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087852
7853 rv = callback.WaitForResult();
7854 EXPECT_EQ(expected_status, rv);
7855}
7856
[email protected]23e482282013-06-14 16:08:027857void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237858 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087859 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427860 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087861}
7862
bncd16676a2016-07-20 16:23:017863TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087864 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7865}
7866
bncd16676a2016-07-20 16:23:017867TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087868 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7869}
7870
bncd16676a2016-07-20 16:23:017871TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087872 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7873}
7874
bncd16676a2016-07-20 16:23:017875TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087876 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7877}
7878
bncd16676a2016-07-20 16:23:017879TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087880 ConnectStatusHelper(
7881 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7882}
7883
bncd16676a2016-07-20 16:23:017884TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087885 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7886}
7887
bncd16676a2016-07-20 16:23:017888TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087889 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7890}
7891
bncd16676a2016-07-20 16:23:017892TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087893 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7894}
7895
bncd16676a2016-07-20 16:23:017896TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087897 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7898}
7899
bncd16676a2016-07-20 16:23:017900TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087901 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7902}
7903
bncd16676a2016-07-20 16:23:017904TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087905 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7906}
7907
bncd16676a2016-07-20 16:23:017908TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087909 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7910}
7911
bncd16676a2016-07-20 16:23:017912TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087913 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7914}
7915
bncd16676a2016-07-20 16:23:017916TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087917 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7918}
7919
bncd16676a2016-07-20 16:23:017920TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087921 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7922}
7923
bncd16676a2016-07-20 16:23:017924TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087925 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7926}
7927
bncd16676a2016-07-20 16:23:017928TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377929 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7930}
7931
bncd16676a2016-07-20 16:23:017932TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087933 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7934}
7935
bncd16676a2016-07-20 16:23:017936TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087937 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7938}
7939
bncd16676a2016-07-20 16:23:017940TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087941 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7942}
7943
bncd16676a2016-07-20 16:23:017944TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087945 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7946}
7947
bncd16676a2016-07-20 16:23:017948TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087949 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7950}
7951
bncd16676a2016-07-20 16:23:017952TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087953 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7954}
7955
bncd16676a2016-07-20 16:23:017956TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087957 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7958}
7959
bncd16676a2016-07-20 16:23:017960TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087961 ConnectStatusHelperWithExpectedStatus(
7962 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547963 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087964}
7965
bncd16676a2016-07-20 16:23:017966TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087967 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7968}
7969
bncd16676a2016-07-20 16:23:017970TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087971 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7972}
7973
bncd16676a2016-07-20 16:23:017974TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087975 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7976}
7977
bncd16676a2016-07-20 16:23:017978TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087979 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7980}
7981
bncd16676a2016-07-20 16:23:017982TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087983 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7984}
7985
bncd16676a2016-07-20 16:23:017986TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087987 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7988}
7989
bncd16676a2016-07-20 16:23:017990TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087991 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7992}
7993
bncd16676a2016-07-20 16:23:017994TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087995 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7996}
7997
bncd16676a2016-07-20 16:23:017998TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087999 ConnectStatusHelper(
8000 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
8001}
8002
bncd16676a2016-07-20 16:23:018003TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:088004 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
8005}
8006
bncd16676a2016-07-20 16:23:018007TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:088008 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
8009}
8010
bncd16676a2016-07-20 16:23:018011TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:088012 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
8013}
8014
bncd16676a2016-07-20 16:23:018015TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:088016 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
8017}
8018
bncd16676a2016-07-20 16:23:018019TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:088020 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
8021}
8022
bncd16676a2016-07-20 16:23:018023TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:088024 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
8025}
8026
bncd16676a2016-07-20 16:23:018027TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:088028 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
8029}
8030
[email protected]038e9a32008-10-08 22:40:168031// Test the flow when both the proxy server AND origin server require
8032// authentication. Again, this uses basic auth for both since that is
8033// the simplest to mock.
bncd16676a2016-07-20 16:23:018034TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:278035 HttpRequestInfo request;
8036 request.method = "GET";
bncce36dca22015-04-21 22:11:238037 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108038 request.traffic_annotation =
8039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278040
[email protected]038e9a32008-10-08 22:40:168041 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:568042 session_deps_.proxy_resolution_service =
8043 ConfiguredProxyResolutionService::CreateFixed(
8044 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:098045 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078046
bnc691fda62016-08-12 00:43:168047 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:168048
[email protected]f9ee6b52008-11-08 06:46:238049 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238050 MockWrite(
8051 "GET http://www.example.org/ HTTP/1.1\r\n"
8052 "Host: www.example.org\r\n"
8053 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238054 };
8055
[email protected]038e9a32008-10-08 22:40:168056 MockRead data_reads1[] = {
8057 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
8058 // Give a couple authenticate options (only the middle one is actually
8059 // supported).
[email protected]22927ad2009-09-21 19:56:198060 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:168061 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8062 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
8063 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8064 // Large content-length -- won't matter, as connection will be reset.
8065 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068066 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:168067 };
8068
bnc691fda62016-08-12 00:43:168069 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:168070 // request we should be issuing -- the final header line contains the
8071 // proxy's credentials.
8072 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238073 MockWrite(
8074 "GET http://www.example.org/ HTTP/1.1\r\n"
8075 "Host: www.example.org\r\n"
8076 "Proxy-Connection: keep-alive\r\n"
8077 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:168078 };
8079
8080 // Now the proxy server lets the request pass through to origin server.
8081 // The origin server responds with a 401.
8082 MockRead data_reads2[] = {
8083 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8084 // Note: We are using the same realm-name as the proxy server. This is
8085 // completely valid, as realms are unique across hosts.
8086 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8087 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8088 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068089 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:168090 };
8091
bnc691fda62016-08-12 00:43:168092 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:168093 // the credentials for both the proxy and origin server.
8094 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238095 MockWrite(
8096 "GET http://www.example.org/ HTTP/1.1\r\n"
8097 "Host: www.example.org\r\n"
8098 "Proxy-Connection: keep-alive\r\n"
8099 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
8100 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:168101 };
8102
8103 // Lastly we get the desired content.
8104 MockRead data_reads3[] = {
8105 MockRead("HTTP/1.0 200 OK\r\n"),
8106 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8107 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068108 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:168109 };
8110
Ryan Sleevib8d7ea02018-05-07 20:01:018111 StaticSocketDataProvider data1(data_reads1, data_writes1);
8112 StaticSocketDataProvider data2(data_reads2, data_writes2);
8113 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078114 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8115 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8116 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:168117
[email protected]49639fa2011-12-20 23:22:418118 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:168119
tfarina42834112016-09-22 13:38:208120 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018121 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168122
8123 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018124 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168125
bnc691fda62016-08-12 00:43:168126 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528127 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588128 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:168129
[email protected]49639fa2011-12-20 23:22:418130 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:168131
bnc691fda62016-08-12 00:43:168132 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:018133 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168134
8135 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018136 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168137
bnc691fda62016-08-12 00:43:168138 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528139 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588140 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:168141
[email protected]49639fa2011-12-20 23:22:418142 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:168143
bnc691fda62016-08-12 00:43:168144 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8145 callback3.callback());
robpercival214763f2016-07-01 23:27:018146 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168147
8148 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018149 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168150
bnc691fda62016-08-12 00:43:168151 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588152 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:168153 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:168154}
[email protected]4ddaf2502008-10-23 18:26:198155
[email protected]ea9dc9a2009-09-05 00:43:328156// For the NTLM implementation using SSPI, we skip the NTLM tests since we
8157// can't hook into its internals to cause it to generate predictable NTLM
8158// authorization headers.
8159#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378160// The NTLM authentication unit tests are based on known test data from the
8161// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
8162// flow rather than the implementation of the NTLM protocol. See net/ntlm
8163// for the implementation and testing of the protocol.
8164//
8165// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:298166
8167// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558168TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:428169 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:248170 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558171 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:108172 request.traffic_annotation =
8173 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548174
8175 // Ensure load is not disrupted by flags which suppress behaviour specific
8176 // to other auth schemes.
8177 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:248178
Asanka Herathbf0b55d2019-12-07 03:27:098179 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098180 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098181 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278182
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378183 // Generate the NTLM messages based on known test data.
8184 std::string negotiate_msg;
8185 std::string challenge_msg;
8186 std::string authenticate_msg;
8187 base::Base64Encode(
8188 base::StringPiece(
8189 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248190 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378191 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558192 base::Base64Encode(
8193 base::StringPiece(
8194 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248195 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558196 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378197 base::Base64Encode(
8198 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098199 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558200 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248201 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558202 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378203 &authenticate_msg);
8204
[email protected]3f918782009-02-28 01:29:248205 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558206 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8207 "Host: server\r\n"
8208 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248209 };
8210
8211 MockRead data_reads1[] = {
8212 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048213 // Negotiate and NTLM are often requested together. However, we only want
8214 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8215 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:248216 MockRead("WWW-Authenticate: NTLM\r\n"),
8217 MockRead("Connection: close\r\n"),
8218 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368219 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248220 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:248221 };
8222
8223 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168224 // After restarting with a null identity, this is the
8225 // request we should be issuing -- the final header line contains a Type
8226 // 1 message.
8227 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558228 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168229 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378230 "Authorization: NTLM "),
8231 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248232
bnc691fda62016-08-12 00:43:168233 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378234 // (using correct credentials). The second request continues on the
8235 // same connection.
bnc691fda62016-08-12 00:43:168236 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558237 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168238 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378239 "Authorization: NTLM "),
8240 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248241 };
8242
8243 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:028244 // The origin server responds with a Type 2 message.
8245 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378246 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8247 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028248 MockRead("Content-Type: text/html\r\n\r\n"),
8249 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:248250
Bence Béky1e4ef192017-09-18 19:58:028251 // Lastly we get the desired content.
8252 MockRead("HTTP/1.1 200 OK\r\n"),
8253 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8254 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:248255 };
8256
Ryan Sleevib8d7ea02018-05-07 20:01:018257 StaticSocketDataProvider data1(data_reads1, data_writes1);
8258 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8260 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:248261
Bence Béky83eb3512017-09-05 12:56:098262 SSLSocketDataProvider ssl1(ASYNC, OK);
8263 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8264 SSLSocketDataProvider ssl2(ASYNC, OK);
8265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8266
[email protected]49639fa2011-12-20 23:22:418267 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:248268
bnc691fda62016-08-12 00:43:168269 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508270
tfarina42834112016-09-22 13:38:208271 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018272 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248273
8274 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018275 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248276
bnc691fda62016-08-12 00:43:168277 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228278
bnc691fda62016-08-12 00:43:168279 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528280 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588281 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:248282
[email protected]49639fa2011-12-20 23:22:418283 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:258284
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378285 rv = trans.RestartWithAuth(
8286 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8287 callback2.callback());
robpercival214763f2016-07-01 23:27:018288 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258289
8290 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018291 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258292
bnc691fda62016-08-12 00:43:168293 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258294
bnc691fda62016-08-12 00:43:168295 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528296 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588297 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:258298
[email protected]49639fa2011-12-20 23:22:418299 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:248300
bnc691fda62016-08-12 00:43:168301 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018302 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248303
[email protected]0757e7702009-03-27 04:00:228304 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018305 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248306
bnc691fda62016-08-12 00:43:168307 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528308 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588309 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028310 EXPECT_EQ(14, response->headers->GetContentLength());
8311
8312 std::string response_data;
8313 rv = ReadTransaction(&trans, &response_data);
8314 EXPECT_THAT(rv, IsOk());
8315 EXPECT_EQ("Please Login\r\n", response_data);
8316
8317 EXPECT_TRUE(data1.AllReadDataConsumed());
8318 EXPECT_TRUE(data1.AllWriteDataConsumed());
8319 EXPECT_TRUE(data2.AllReadDataConsumed());
8320 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:248321}
8322
[email protected]385a4672009-03-11 22:21:298323// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558324TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:428325 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:298326 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558327 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:108328 request.traffic_annotation =
8329 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:298330
Asanka Herathbf0b55d2019-12-07 03:27:098331 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098332 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098333 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278334
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378335 // Generate the NTLM messages based on known test data.
8336 std::string negotiate_msg;
8337 std::string challenge_msg;
8338 std::string authenticate_msg;
8339 base::Base64Encode(
8340 base::StringPiece(
8341 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248342 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378343 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558344 base::Base64Encode(
8345 base::StringPiece(
8346 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248347 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558348 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378349 base::Base64Encode(
8350 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098351 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558352 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248353 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558354 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378355 &authenticate_msg);
8356
8357 // The authenticate message when |kWrongPassword| is sent.
8358 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558359 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
8360 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
8361 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
8362 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
8363 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
8364 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378365
Zentaro Kavanagh1890a3d2018-01-29 19:52:558366 // Sanity check that it's the same length as the correct authenticate message
8367 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378368 ASSERT_EQ(authenticate_msg.length(),
8369 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:558370 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378371
[email protected]385a4672009-03-11 22:21:298372 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558373 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8374 "Host: server\r\n"
8375 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298376 };
8377
8378 MockRead data_reads1[] = {
8379 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048380 // Negotiate and NTLM are often requested together. However, we only want
8381 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8382 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:298383 MockRead("WWW-Authenticate: NTLM\r\n"),
8384 MockRead("Connection: close\r\n"),
8385 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368386 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298387 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298388 };
8389
8390 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168391 // After restarting with a null identity, this is the
8392 // request we should be issuing -- the final header line contains a Type
8393 // 1 message.
8394 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558395 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168396 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378397 "Authorization: NTLM "),
8398 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298399
bnc691fda62016-08-12 00:43:168400 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378401 // (using incorrect credentials). The second request continues on the
8402 // same connection.
bnc691fda62016-08-12 00:43:168403 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558404 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168405 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378406 "Authorization: NTLM "),
8407 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298408 };
8409
8410 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378411 // The origin server responds with a Type 2 message.
8412 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8413 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8414 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8415 MockRead("Content-Type: text/html\r\n\r\n"),
8416 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298417
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378418 // Wrong password.
8419 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8420 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8421 MockRead("Content-Length: 42\r\n"),
8422 MockRead("Content-Type: text/html\r\n\r\n"),
8423 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298424 };
8425
8426 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168427 // After restarting with a null identity, this is the
8428 // request we should be issuing -- the final header line contains a Type
8429 // 1 message.
8430 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558431 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168432 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378433 "Authorization: NTLM "),
8434 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298435
bnc691fda62016-08-12 00:43:168436 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8437 // (the credentials for the origin server). The second request continues
8438 // on the same connection.
8439 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558440 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168441 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378442 "Authorization: NTLM "),
8443 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298444 };
8445
8446 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028447 // The origin server responds with a Type 2 message.
8448 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378449 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8450 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028451 MockRead("Content-Type: text/html\r\n\r\n"),
8452 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298453
Bence Béky1e4ef192017-09-18 19:58:028454 // Lastly we get the desired content.
8455 MockRead("HTTP/1.1 200 OK\r\n"),
8456 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8457 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298458 };
8459
Ryan Sleevib8d7ea02018-05-07 20:01:018460 StaticSocketDataProvider data1(data_reads1, data_writes1);
8461 StaticSocketDataProvider data2(data_reads2, data_writes2);
8462 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078463 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8464 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8465 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298466
Bence Béky83eb3512017-09-05 12:56:098467 SSLSocketDataProvider ssl1(ASYNC, OK);
8468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8469 SSLSocketDataProvider ssl2(ASYNC, OK);
8470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8471 SSLSocketDataProvider ssl3(ASYNC, OK);
8472 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8473
[email protected]49639fa2011-12-20 23:22:418474 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298475
bnc691fda62016-08-12 00:43:168476 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508477
tfarina42834112016-09-22 13:38:208478 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018479 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298480
8481 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018482 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298483
bnc691fda62016-08-12 00:43:168484 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298485
bnc691fda62016-08-12 00:43:168486 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528487 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588488 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298489
[email protected]49639fa2011-12-20 23:22:418490 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298491
[email protected]0757e7702009-03-27 04:00:228492 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378493 rv = trans.RestartWithAuth(
8494 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8495 callback2.callback());
robpercival214763f2016-07-01 23:27:018496 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298497
[email protected]10af5fe72011-01-31 16:17:258498 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018499 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298500
bnc691fda62016-08-12 00:43:168501 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418502 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168503 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258505 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018506 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168507 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228508
bnc691fda62016-08-12 00:43:168509 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528510 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588511 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228512
[email protected]49639fa2011-12-20 23:22:418513 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228514
8515 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378516 rv = trans.RestartWithAuth(
8517 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8518 callback4.callback());
robpercival214763f2016-07-01 23:27:018519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258520
8521 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018522 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258523
bnc691fda62016-08-12 00:43:168524 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258525
[email protected]49639fa2011-12-20 23:22:418526 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258527
8528 // One more roundtrip
bnc691fda62016-08-12 00:43:168529 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228531
8532 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018533 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228534
bnc691fda62016-08-12 00:43:168535 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588536 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028537 EXPECT_EQ(14, response->headers->GetContentLength());
8538
8539 std::string response_data;
8540 rv = ReadTransaction(&trans, &response_data);
8541 EXPECT_THAT(rv, IsOk());
8542 EXPECT_EQ("Please Login\r\n", response_data);
8543
8544 EXPECT_TRUE(data1.AllReadDataConsumed());
8545 EXPECT_TRUE(data1.AllWriteDataConsumed());
8546 EXPECT_TRUE(data2.AllReadDataConsumed());
8547 EXPECT_TRUE(data2.AllWriteDataConsumed());
8548 EXPECT_TRUE(data3.AllReadDataConsumed());
8549 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298550}
Bence Béky83eb3512017-09-05 12:56:098551
Bence Béky3238f2e12017-09-22 22:44:498552// Server requests NTLM authentication, which is not supported over HTTP/2.
8553// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098554TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Asanka Herathbf0b55d2019-12-07 03:27:098555 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098556 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098557
Zentaro Kavanagh1890a3d2018-01-29 19:52:558558 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098559
8560 HttpRequestInfo request;
8561 request.method = "GET";
8562 request.url = GURL(kUrl);
Ramin Halavatib5e433e2018-02-07 07:41:108563 request.traffic_annotation =
8564 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098565
8566 // First request without credentials.
Bence Béky4c325e52020-10-22 20:48:018567 spdy::Http2HeaderBlock request_headers0(
Ryan Hamilton0239aac2018-05-19 00:03:138568 spdy_util_.ConstructGetHeaderBlock(kUrl));
8569 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098570 1, std::move(request_headers0), LOWEST, true));
8571
Bence Béky4c325e52020-10-22 20:48:018572 spdy::Http2HeaderBlock response_headers0;
Ryan Hamilton0239aac2018-05-19 00:03:138573 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098574 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138575 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098576 1, std::move(response_headers0), true));
8577
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378578 // Stream 1 is closed.
8579 spdy_util_.UpdateWithStreamDestruction(1);
8580
8581 // Generate the NTLM messages based on known test data.
8582 std::string negotiate_msg;
8583 std::string challenge_msg;
8584 std::string authenticate_msg;
8585 base::Base64Encode(
8586 base::StringPiece(
8587 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248588 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378589 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558590 base::Base64Encode(
8591 base::StringPiece(
8592 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248593 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558594 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378595 base::Base64Encode(
8596 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098597 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558598 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248599 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558600 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378601 &authenticate_msg);
8602
Bence Béky3238f2e12017-09-22 22:44:498603 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168604 MockRead reads0[] = {CreateMockRead(resp, 1),
8605 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098606
8607 // Retry yet again using HTTP/1.1.
8608 MockWrite writes1[] = {
8609 // After restarting with a null identity, this is the
8610 // request we should be issuing -- the final header line contains a Type
8611 // 1 message.
8612 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558613 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098614 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378615 "Authorization: NTLM "),
8616 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098617
8618 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8619 // (the credentials for the origin server). The second request continues
8620 // on the same connection.
8621 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558622 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098623 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378624 "Authorization: NTLM "),
8625 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098626 };
8627
8628 MockRead reads1[] = {
8629 // The origin server responds with a Type 2 message.
8630 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378631 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8632 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098633 MockRead("Content-Type: text/html\r\n\r\n"),
8634 MockRead("You are not authorized to view this page\r\n"),
8635
8636 // Lastly we get the desired content.
8637 MockRead("HTTP/1.1 200 OK\r\n"),
8638 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028639 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098640 };
Ryan Sleevib8d7ea02018-05-07 20:01:018641 SequencedSocketData data0(reads0, writes0);
8642 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098643 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8644 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8645
8646 SSLSocketDataProvider ssl0(ASYNC, OK);
8647 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168648 ssl0.next_protos_expected_in_ssl_config =
8649 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098650 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168651 // When creating the second connection, only HTTP/1.1 should be allowed.
8652 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8654 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8655
8656 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8657 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8658
8659 TestCompletionCallback callback1;
8660 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8661 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8662
8663 rv = callback1.WaitForResult();
8664 EXPECT_THAT(rv, IsOk());
8665
8666 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8667
8668 const HttpResponseInfo* response = trans.GetResponseInfo();
8669 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588670 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098671
8672 TestCompletionCallback callback2;
8673
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378674 rv = trans.RestartWithAuth(
8675 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8676 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8678
8679 rv = callback2.WaitForResult();
8680 EXPECT_THAT(rv, IsOk());
8681
8682 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8683
8684 response = trans.GetResponseInfo();
8685 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588686 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098687
8688 TestCompletionCallback callback3;
8689
8690 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8691 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8692
8693 rv = callback3.WaitForResult();
8694 EXPECT_THAT(rv, IsOk());
8695
8696 response = trans.GetResponseInfo();
8697 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588698 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028699 EXPECT_EQ(14, response->headers->GetContentLength());
8700
8701 std::string response_data;
8702 rv = ReadTransaction(&trans, &response_data);
8703 EXPECT_THAT(rv, IsOk());
8704 EXPECT_EQ("Please Login\r\n", response_data);
8705
8706 EXPECT_TRUE(data0.AllReadDataConsumed());
8707 EXPECT_TRUE(data0.AllWriteDataConsumed());
8708 EXPECT_TRUE(data1.AllReadDataConsumed());
8709 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098710}
David Benjamin5cb91132018-04-06 05:54:498711
Matt Menkef2ee07c2019-08-29 02:10:368712#if BUILDFLAG(ENABLE_WEBSOCKETS)
8713
8714// Variant of above test using WebSockets.
8715TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8716 const GURL kInitialUrl("https://server/");
8717 const GURL kWebSocketUrl("wss://server/");
Asanka Herathbf0b55d2019-12-07 03:27:098718 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Matt Menkef2ee07c2019-08-29 02:10:368719 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8720
8721 // Initial request establishes an H2 connection, which will then be reused for
8722 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8723 // it won't create a new one.
Bence Béky4c325e52020-10-22 20:48:018724 spdy::Http2HeaderBlock initial_request_headers(
Matt Menkef2ee07c2019-08-29 02:10:368725 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8726 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8727 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8728 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8729
8730 // Settings frame, indicating WebSockets is supported.
8731 spdy::SettingsMap settings;
8732 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8733 spdy::SpdySerializedFrame settings_frame(
8734 spdy_util_.ConstructSpdySettings(settings));
8735
8736 // Response headers for first request. Body is never received, but that
8737 // shouldn't matter for the purposes of this test.
8738 spdy::SpdySerializedFrame initial_response(
8739 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8740
8741 // First WebSocket request, which has no credentials.
Bence Béky4c325e52020-10-22 20:48:018742 spdy::Http2HeaderBlock websocket_request_headers;
Matt Menkef2ee07c2019-08-29 02:10:368743 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8744 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8745 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8746 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8747 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8748 websocket_request_headers["origin"] = "http://server";
8749 websocket_request_headers["sec-websocket-version"] = "13";
8750 websocket_request_headers["sec-websocket-extensions"] =
8751 "permessage-deflate; client_max_window_bits";
8752 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8753 3, std::move(websocket_request_headers), MEDIUM, false));
8754
8755 // Auth challenge to WebSocket request.
Bence Béky4c325e52020-10-22 20:48:018756 spdy::Http2HeaderBlock auth_challenge_headers;
Matt Menkef2ee07c2019-08-29 02:10:368757 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8758 auth_challenge_headers["www-authenticate"] = "NTLM";
8759 spdy::SpdySerializedFrame websocket_auth_challenge(
8760 spdy_util_.ConstructSpdyResponseHeaders(
8761 3, std::move(auth_challenge_headers), true));
8762
8763 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8764 CreateMockWrite(settings_ack, 2),
8765 CreateMockWrite(websocket_request, 4),
8766 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8767 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8768 CreateMockRead(initial_response, 3),
8769 CreateMockRead(websocket_auth_challenge, 5),
8770 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8771
8772 // Generate the NTLM messages based on known test data.
8773 std::string negotiate_msg;
8774 std::string challenge_msg;
8775 std::string authenticate_msg;
8776 base::Base64Encode(
8777 base::StringPiece(
8778 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8779 base::size(ntlm::test::kExpectedNegotiateMsg)),
8780 &negotiate_msg);
8781 base::Base64Encode(
8782 base::StringPiece(
8783 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8784 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8785 &challenge_msg);
8786 base::Base64Encode(
8787 base::StringPiece(
8788 reinterpret_cast<const char*>(
8789 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8790 base::size(
8791 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8792 &authenticate_msg);
8793
8794 // Retry yet again using HTTP/1.1.
8795 MockWrite writes1[] = {
8796 // After restarting with a null identity, this is the
8797 // request we should be issuing -- the final header line contains a Type
8798 // 1 message.
8799 MockWrite("GET / HTTP/1.1\r\n"
8800 "Host: server\r\n"
8801 "Connection: Upgrade\r\n"
8802 "Authorization: NTLM "),
8803 MockWrite(negotiate_msg.c_str()),
8804 MockWrite("\r\n"),
8805 MockWrite("Origin: http://server\r\n"
8806 "Sec-WebSocket-Version: 13\r\n"
8807 "Upgrade: websocket\r\n"
8808 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8809 "Sec-WebSocket-Extensions: permessage-deflate; "
8810 "client_max_window_bits\r\n\r\n"),
8811
8812 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8813 // (the credentials for the origin server). The second request continues
8814 // on the same connection.
8815 MockWrite("GET / HTTP/1.1\r\n"
8816 "Host: server\r\n"
8817 "Connection: Upgrade\r\n"
8818 "Authorization: NTLM "),
8819 MockWrite(authenticate_msg.c_str()),
8820 MockWrite("\r\n"),
8821 MockWrite("Origin: http://server\r\n"
8822 "Sec-WebSocket-Version: 13\r\n"
8823 "Upgrade: websocket\r\n"
8824 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8825 "Sec-WebSocket-Extensions: permessage-deflate; "
8826 "client_max_window_bits\r\n\r\n"),
8827 };
8828
8829 MockRead reads1[] = {
8830 // The origin server responds with a Type 2 message.
8831 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8832 MockRead("WWW-Authenticate: NTLM "),
8833 MockRead(challenge_msg.c_str()),
8834 MockRead("\r\n"),
8835 MockRead("Content-Length: 42\r\n"),
8836 MockRead("Content-Type: text/html\r\n\r\n"),
8837 MockRead("You are not authorized to view this page\r\n"),
8838
8839 // Lastly we get the desired content.
8840 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8841 "Upgrade: websocket\r\n"
8842 "Connection: Upgrade\r\n"
8843 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8844 };
8845 SequencedSocketData data0(reads0, writes0);
8846 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8847 SSLSocketDataProvider ssl0(ASYNC, OK);
8848 ssl0.next_proto = kProtoHTTP2;
8849 ssl0.next_protos_expected_in_ssl_config =
8850 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8852
8853 StaticSocketDataProvider data1(reads1, writes1);
8854 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8855 SSLSocketDataProvider ssl1(ASYNC, OK);
8856 // When creating the second connection, only HTTP/1.1 should be allowed.
8857 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8858 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8859
8860 session_deps_.enable_websocket_over_http2 = true;
8861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8862
8863 HttpRequestInfo initial_request_info;
8864 initial_request_info.method = "GET";
8865 initial_request_info.url = kInitialUrl;
8866 initial_request_info.traffic_annotation =
8867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8868 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8869 TestCompletionCallback initial_callback;
8870 int rv = initial_trans.Start(&initial_request_info,
8871 initial_callback.callback(), NetLogWithSource());
8872 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8873
8874 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8875 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8876
8877 HttpRequestInfo websocket_request_info;
8878 websocket_request_info.method = "GET";
8879 websocket_request_info.url = kWebSocketUrl;
8880 websocket_request_info.traffic_annotation =
8881 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8882 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8883 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8884 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8885 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8886 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8887 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8888 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8889
8890 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8891
8892 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8893 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8894 &websocket_stream_create_helper);
8895
8896 TestCompletionCallback websocket_callback;
8897 rv = websocket_trans.Start(&websocket_request_info,
8898 websocket_callback.callback(), NetLogWithSource());
8899 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8900
8901 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8902
8903 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8904 ASSERT_TRUE(response);
8905 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8906
8907 rv = websocket_trans.RestartWithAuth(
8908 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8909 websocket_callback.callback());
8910 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8911
8912 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8913
8914 response = websocket_trans.GetResponseInfo();
8915 ASSERT_TRUE(response);
8916 EXPECT_FALSE(response->auth_challenge.has_value());
8917
8918 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8919 websocket_callback.callback());
8920 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8921
8922 // The server should have been marked as requiring HTTP/1.1. The important
8923 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8924 // WSS.
8925 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8926 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8927}
8928
8929#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8930
David Benjamin5cb91132018-04-06 05:54:498931// Test that, if we have an NTLM proxy and the origin resets the connection, we
David Benjamin07a07d652020-02-26 22:26:598932// do no retry forever as a result of TLS retries. This is a regression test for
8933// https://crbug.com/823387. The version interference probe has since been
8934// removed, but we now have a legacy crypto fallback. (If that fallback is
8935// removed, this test should be kept but with the expectations tweaked, in case
8936// future fallbacks are added.)
David Benjamin5cb91132018-04-06 05:54:498937TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8938 // The NTLM test data expects the proxy to be named 'server'. The origin is
8939 // https://origin/.
8940 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:568941 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
David Benjamin5cb91132018-04-06 05:54:498942 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8943
David Benjamin151ec6b2019-08-02 19:38:528944 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498945 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078946 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498947
8948 HttpRequestInfo request;
8949 request.method = "GET";
8950 request.url = GURL("https://origin/");
8951 request.traffic_annotation =
8952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8953
8954 // Ensure load is not disrupted by flags which suppress behaviour specific
8955 // to other auth schemes.
8956 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8957
Asanka Herathbf0b55d2019-12-07 03:27:098958 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
David Benjamin5cb91132018-04-06 05:54:498959 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8961
8962 // Generate the NTLM messages based on known test data.
8963 std::string negotiate_msg;
8964 std::string challenge_msg;
8965 std::string authenticate_msg;
8966 base::Base64Encode(
8967 base::StringPiece(
8968 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248969 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498970 &negotiate_msg);
8971 base::Base64Encode(
8972 base::StringPiece(
8973 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248974 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498975 &challenge_msg);
8976 base::Base64Encode(
8977 base::StringPiece(
8978 reinterpret_cast<const char*>(
8979 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248980 base::size(
David Benjamin5cb91132018-04-06 05:54:498981 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8982 &authenticate_msg);
8983
8984 MockWrite data_writes[] = {
8985 // The initial CONNECT request.
8986 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8987 "Host: origin:443\r\n"
8988 "Proxy-Connection: keep-alive\r\n\r\n"),
8989
8990 // After restarting with an identity.
8991 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8992 "Host: origin:443\r\n"
8993 "Proxy-Connection: keep-alive\r\n"
8994 "Proxy-Authorization: NTLM "),
8995 MockWrite(negotiate_msg.c_str()),
8996 // End headers.
8997 MockWrite("\r\n\r\n"),
8998
8999 // The second restart.
9000 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
9001 "Host: origin:443\r\n"
9002 "Proxy-Connection: keep-alive\r\n"
9003 "Proxy-Authorization: NTLM "),
9004 MockWrite(authenticate_msg.c_str()),
9005 // End headers.
9006 MockWrite("\r\n\r\n"),
9007 };
9008
9009 MockRead data_reads[] = {
9010 // The initial NTLM response.
9011 MockRead("HTTP/1.1 407 Access Denied\r\n"
9012 "Content-Length: 0\r\n"
9013 "Proxy-Authenticate: NTLM\r\n\r\n"),
9014
9015 // The NTLM challenge message.
9016 MockRead("HTTP/1.1 407 Access Denied\r\n"
9017 "Content-Length: 0\r\n"
9018 "Proxy-Authenticate: NTLM "),
9019 MockRead(challenge_msg.c_str()),
9020 // End headers.
9021 MockRead("\r\n\r\n"),
9022
9023 // Finally the tunnel is established.
9024 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
9025 };
9026
Ryan Sleevib8d7ea02018-05-07 20:01:019027 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:499028 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:499029 session_deps_.socket_factory->AddSocketDataProvider(&data);
9030 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:499031
David Benjamin07a07d652020-02-26 22:26:599032 StaticSocketDataProvider data2(data_reads, data_writes);
9033 SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
9034 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9035 session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);
9036
David Benjamin5cb91132018-04-06 05:54:499037 // Start the transaction. The proxy responds with an NTLM authentication
9038 // request.
9039 TestCompletionCallback callback;
9040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9041 int rv = callback.GetResult(
9042 trans.Start(&request, callback.callback(), NetLogWithSource()));
9043
9044 EXPECT_THAT(rv, IsOk());
9045 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
9046 const HttpResponseInfo* response = trans.GetResponseInfo();
9047 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589048 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:499049
David Benjamind61bd532019-04-23 21:11:379050 // Configure credentials and restart. The proxy responds with the challenge
9051 // message.
David Benjamin5cb91132018-04-06 05:54:499052 rv = callback.GetResult(trans.RestartWithAuth(
9053 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
9054 callback.callback()));
9055 EXPECT_THAT(rv, IsOk());
9056 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9057 response = trans.GetResponseInfo();
9058 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589059 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:499060
David Benjamin07a07d652020-02-26 22:26:599061 // Restart once more. The tunnel will be established and the the SSL handshake
9062 // will reset. The fallback will then kick in and restart the process. The
9063 // proxy responds with another NTLM authentiation request, but we don't need
9064 // to provide credentials as the cached ones work.
9065 rv = callback.GetResult(
9066 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9067 EXPECT_THAT(rv, IsOk());
9068 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9069 response = trans.GetResponseInfo();
9070 ASSERT_TRUE(response);
9071 EXPECT_FALSE(response->auth_challenge.has_value());
9072
9073 // The proxy responds with the NTLM challenge message.
9074 rv = callback.GetResult(
9075 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9076 EXPECT_THAT(rv, IsOk());
9077 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9078 response = trans.GetResponseInfo();
9079 ASSERT_TRUE(response);
9080 EXPECT_FALSE(response->auth_challenge.has_value());
9081
9082 // Send the NTLM authenticate message. The tunnel is established and the
9083 // handshake resets again. We should not retry again.
David Benjamin5cb91132018-04-06 05:54:499084 rv = callback.GetResult(
9085 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9086 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
9087}
9088
[email protected]ea9dc9a2009-09-05 00:43:329089#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:299090
[email protected]4ddaf2502008-10-23 18:26:199091// Test reading a server response which has only headers, and no body.
9092// After some maximum number of bytes is consumed, the transaction should
9093// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:019094TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:429095 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:199096 request.method = "GET";
bncce36dca22015-04-21 22:11:239097 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109098 request.traffic_annotation =
9099 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:199100
danakj1fd259a02016-04-16 03:17:099101 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169102 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279103
[email protected]b75b7b2f2009-10-06 00:54:539104 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:439105 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:539106 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:199107
9108 MockRead data_reads[] = {
9109 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:069110 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:199111 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:069112 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:199113 };
Ryan Sleevib8d7ea02018-05-07 20:01:019114 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079115 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:199116
[email protected]49639fa2011-12-20 23:22:419117 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:199118
tfarina42834112016-09-22 13:38:209119 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:199121
9122 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019123 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:199124}
[email protected]f4e426b2008-11-05 00:24:499125
9126// Make sure that we don't try to reuse a TCPClientSocket when failing to
9127// establish tunnel.
9128// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:019129TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:279130 HttpRequestInfo request;
9131 request.method = "GET";
bncce36dca22015-04-21 22:11:239132 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109133 request.traffic_annotation =
9134 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:279135
[email protected]f4e426b2008-11-05 00:24:499136 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:569137 session_deps_.proxy_resolution_service =
9138 ConfiguredProxyResolutionService::CreateFixed(
9139 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:019140
danakj1fd259a02016-04-16 03:17:099141 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:499142
bnc87dcefc2017-05-25 12:47:589143 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199144 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:499145
[email protected]f4e426b2008-11-05 00:24:499146 // Since we have proxy, should try to establish tunnel.
9147 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:179148 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9149 "Host: www.example.org:443\r\n"
9150 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:499151 };
9152
[email protected]77848d12008-11-14 00:00:229153 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:499154 // connection. Usually a proxy would return 501 (not implemented),
9155 // or 200 (tunnel established).
9156 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:239157 MockRead("HTTP/1.1 404 Not Found\r\n"),
9158 MockRead("Content-Length: 10\r\n\r\n"),
9159 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:499160 };
9161
Ryan Sleevib8d7ea02018-05-07 20:01:019162 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079163 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:499164
[email protected]49639fa2011-12-20 23:22:419165 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:499166
tfarina42834112016-09-22 13:38:209167 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019168 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:499169
9170 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019171 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:499172
[email protected]b4404c02009-04-10 16:38:529173 // Empty the current queue. This is necessary because idle sockets are
9174 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559175 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529176
[email protected]f4e426b2008-11-05 00:24:499177 // We now check to make sure the TCPClientSocket was not added back to
9178 // the pool.
[email protected]90499482013-06-01 00:39:509179 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:499180 trans.reset();
fdoray92e35a72016-06-10 15:54:559181 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:499182 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:509183 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:499184}
[email protected]372d34a2008-11-05 21:30:519185
[email protected]1b157c02009-04-21 01:55:409186// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:019187TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:429188 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:409189 request.method = "GET";
bncce36dca22015-04-21 22:11:239190 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109191 request.traffic_annotation =
9192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:409193
danakj1fd259a02016-04-16 03:17:099194 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279195
bnc691fda62016-08-12 00:43:169196 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279197
[email protected]1b157c02009-04-21 01:55:409198 MockRead data_reads[] = {
9199 // A part of the response body is received with the response headers.
9200 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9201 // The rest of the response body is received in two parts.
9202 MockRead("lo"),
9203 MockRead(" world"),
9204 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069205 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:409206 };
9207
Ryan Sleevib8d7ea02018-05-07 20:01:019208 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079209 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:409210
[email protected]49639fa2011-12-20 23:22:419211 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:409212
tfarina42834112016-09-22 13:38:209213 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019214 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:409215
9216 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019217 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:409218
bnc691fda62016-08-12 00:43:169219 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529220 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:409221
wezca1070932016-05-26 20:30:529222 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:409223 std::string status_line = response->headers->GetStatusLine();
9224 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9225
[email protected]90499482013-06-01 00:39:509226 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:409227
9228 std::string response_data;
bnc691fda62016-08-12 00:43:169229 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019230 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:409231 EXPECT_EQ("hello world", response_data);
9232
9233 // Empty the current queue. This is necessary because idle sockets are
9234 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559235 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:409236
9237 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509238 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:409239}
9240
[email protected]76a505b2010-08-25 06:23:009241// Make sure that we recycle a SSL socket after reading all of the response
9242// body.
bncd16676a2016-07-20 16:23:019243TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:009244 HttpRequestInfo request;
9245 request.method = "GET";
bncce36dca22015-04-21 22:11:239246 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109247 request.traffic_annotation =
9248 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:009249
9250 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239251 MockWrite(
9252 "GET / HTTP/1.1\r\n"
9253 "Host: www.example.org\r\n"
9254 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009255 };
9256
9257 MockRead data_reads[] = {
9258 MockRead("HTTP/1.1 200 OK\r\n"),
9259 MockRead("Content-Length: 11\r\n\r\n"),
9260 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069261 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:009262 };
9263
[email protected]8ddf8322012-02-23 18:08:069264 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:009266
Ryan Sleevib8d7ea02018-05-07 20:01:019267 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079268 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:009269
[email protected]49639fa2011-12-20 23:22:419270 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009271
danakj1fd259a02016-04-16 03:17:099272 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169273 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009274
tfarina42834112016-09-22 13:38:209275 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009276
robpercival214763f2016-07-01 23:27:019277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9278 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009279
bnc691fda62016-08-12 00:43:169280 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529281 ASSERT_TRUE(response);
9282 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009283 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9284
[email protected]90499482013-06-01 00:39:509285 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009286
9287 std::string response_data;
bnc691fda62016-08-12 00:43:169288 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019289 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009290 EXPECT_EQ("hello world", response_data);
9291
9292 // Empty the current queue. This is necessary because idle sockets are
9293 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559294 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009295
9296 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239297 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009298}
9299
9300// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
9301// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:019302TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:009303 HttpRequestInfo request;
9304 request.method = "GET";
bncce36dca22015-04-21 22:11:239305 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109306 request.traffic_annotation =
9307 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:009308
9309 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239310 MockWrite(
9311 "GET / HTTP/1.1\r\n"
9312 "Host: www.example.org\r\n"
9313 "Connection: keep-alive\r\n\r\n"),
9314 MockWrite(
9315 "GET / HTTP/1.1\r\n"
9316 "Host: www.example.org\r\n"
9317 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009318 };
9319
9320 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:429321 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9322 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:009323
[email protected]8ddf8322012-02-23 18:08:069324 SSLSocketDataProvider ssl(ASYNC, OK);
9325 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9327 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:009328
Ryan Sleevib8d7ea02018-05-07 20:01:019329 StaticSocketDataProvider data(data_reads, data_writes);
9330 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079331 session_deps_.socket_factory->AddSocketDataProvider(&data);
9332 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:009333
[email protected]49639fa2011-12-20 23:22:419334 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009335
danakj1fd259a02016-04-16 03:17:099336 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:589337 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199338 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009339
tfarina42834112016-09-22 13:38:209340 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009341
robpercival214763f2016-07-01 23:27:019342 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9343 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009344
9345 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529346 ASSERT_TRUE(response);
9347 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009348 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9349
[email protected]90499482013-06-01 00:39:509350 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009351
9352 std::string response_data;
9353 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019354 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009355 EXPECT_EQ("hello world", response_data);
9356
9357 // Empty the current queue. This is necessary because idle sockets are
9358 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559359 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009360
9361 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239362 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009363
9364 // Now start the second transaction, which should reuse the previous socket.
9365
bnc87dcefc2017-05-25 12:47:589366 trans =
Jeremy Roman0579ed62017-08-29 15:56:199367 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009368
tfarina42834112016-09-22 13:38:209369 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009370
robpercival214763f2016-07-01 23:27:019371 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9372 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009373
9374 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529375 ASSERT_TRUE(response);
9376 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009377 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9378
[email protected]90499482013-06-01 00:39:509379 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009380
9381 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019382 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009383 EXPECT_EQ("hello world", response_data);
9384
9385 // Empty the current queue. This is necessary because idle sockets are
9386 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559387 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009388
9389 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239390 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009391}
9392
Matt Menke2451c8b2020-12-08 22:42:519393TEST_F(HttpNetworkTransactionTest, CloseConnectionOnDestruction) {
9394 enum class TestCase {
9395 kReadHeaders,
9396 kReadPartOfBodyRead,
9397 kReadAllOfBody,
9398 };
9399
9400 for (auto test_case : {TestCase::kReadHeaders, TestCase::kReadPartOfBodyRead,
9401 TestCase::kReadAllOfBody}) {
9402 SCOPED_TRACE(testing::Message()
9403 << "Test case: " << static_cast<int>(test_case));
9404 for (bool close_connection : {false, true}) {
9405 if (test_case != TestCase::kReadAllOfBody || close_connection == false)
9406 continue;
9407 SCOPED_TRACE(testing::Message()
9408 << "Close connection: " << close_connection);
9409
9410 HttpRequestInfo request;
9411 request.method = "GET";
9412 request.url = GURL("http://foo.test/");
9413 request.traffic_annotation =
9414 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9415
9416 std::unique_ptr<HttpNetworkSession> session(
9417 CreateSession(&session_deps_));
9418
9419 std::unique_ptr<HttpNetworkTransaction> trans =
9420 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
9421 session.get());
9422
9423 MockRead data_reads[] = {
9424 // A part of the response body is received with the response headers.
9425 MockRead("HTTP/1.1 200 OK\r\n"
9426 "Content-Length: 11\r\n\r\n"
9427 "hello world"),
9428 MockRead(SYNCHRONOUS, OK),
9429 };
9430
9431 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
9432 session_deps_.socket_factory->AddSocketDataProvider(&data);
9433
9434 TestCompletionCallback callback;
9435
9436 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
9437 EXPECT_THAT(callback.GetResult(rv), IsOk());
9438
9439 const HttpResponseInfo* response = trans->GetResponseInfo();
9440 ASSERT_TRUE(response);
9441
9442 EXPECT_TRUE(response->headers);
9443 std::string status_line = response->headers->GetStatusLine();
9444 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9445
9446 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9447
9448 std::string response_data;
9449 switch (test_case) {
9450 case TestCase::kReadHeaders: {
9451 // Already read the headers, nothing else to do.
9452 break;
9453 }
9454
9455 case TestCase::kReadPartOfBodyRead: {
9456 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(5);
9457 rv = trans->Read(buf.get(), 5, callback.callback());
9458 ASSERT_EQ(5, callback.GetResult(rv));
9459 response_data.assign(buf->data(), 5);
9460 EXPECT_EQ("hello", response_data);
9461 break;
9462 }
9463
9464 case TestCase::kReadAllOfBody: {
9465 rv = ReadTransaction(trans.get(), &response_data);
9466 EXPECT_THAT(rv, IsOk());
9467 EXPECT_EQ("hello world", response_data);
9468 break;
9469 }
9470 }
9471
9472 if (close_connection)
9473 trans->CloseConnectionOnDestruction();
9474 trans.reset();
9475
9476 // Wait for the socket to be drained and added to the socket pool or
9477 // destroyed.
9478 base::RunLoop().RunUntilIdle();
9479
9480 // In the case all the body was read, the socket will have been released
9481 // before the CloseConnectionOnDestruction() call, so will not be
9482 // destroyed.
9483 if (close_connection && test_case != TestCase::kReadAllOfBody) {
9484 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9485 } else {
9486 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9487 }
9488 }
9489 }
9490}
9491
maksim.sisov0adf8592016-07-15 06:25:569492// Grab a socket, use it, and put it back into the pool. Then, make
9493// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019494TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569495 HttpRequestInfo request;
9496 request.method = "GET";
9497 request.url = GURL("http://www.example.org/");
9498 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109499 request.traffic_annotation =
9500 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569501
9502 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9503
bnc691fda62016-08-12 00:43:169504 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569505
9506 MockRead data_reads[] = {
9507 // A part of the response body is received with the response headers.
9508 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9509 // The rest of the response body is received in two parts.
9510 MockRead("lo"), MockRead(" world"),
9511 MockRead("junk"), // Should not be read!!
9512 MockRead(SYNCHRONOUS, OK),
9513 };
9514
Ryan Sleevib8d7ea02018-05-07 20:01:019515 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569516 session_deps_.socket_factory->AddSocketDataProvider(&data);
9517
9518 TestCompletionCallback callback;
9519
tfarina42834112016-09-22 13:38:209520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569521 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9522
9523 EXPECT_THAT(callback.GetResult(rv), IsOk());
9524
bnc691fda62016-08-12 00:43:169525 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569526 ASSERT_TRUE(response);
9527 EXPECT_TRUE(response->headers);
9528 std::string status_line = response->headers->GetStatusLine();
9529 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9530
9531 // Make memory critical notification and ensure the transaction still has been
9532 // operating right.
9533 base::MemoryPressureListener::NotifyMemoryPressure(
9534 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9535 base::RunLoop().RunUntilIdle();
9536
9537 // Socket should not be flushed as long as it is not idle.
9538 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9539
9540 std::string response_data;
bnc691fda62016-08-12 00:43:169541 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569542 EXPECT_THAT(rv, IsOk());
9543 EXPECT_EQ("hello world", response_data);
9544
9545 // Empty the current queue. This is necessary because idle sockets are
9546 // added to the connection pool asynchronously with a PostTask.
9547 base::RunLoop().RunUntilIdle();
9548
9549 // We now check to make sure the socket was added back to the pool.
9550 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9551
9552 // Idle sockets should be flushed now.
9553 base::MemoryPressureListener::NotifyMemoryPressure(
9554 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9555 base::RunLoop().RunUntilIdle();
9556
9557 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9558}
9559
yucliu48f235d2018-01-11 00:59:559560// Disable idle socket closing on memory pressure.
9561// Grab a socket, use it, and put it back into the pool. Then, make
9562// low memory notification and ensure the socket pool is NOT flushed.
9563TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9564 HttpRequestInfo request;
9565 request.method = "GET";
9566 request.url = GURL("http://www.example.org/");
9567 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109568 request.traffic_annotation =
9569 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559570
9571 // Disable idle socket closing on memory pressure.
9572 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9574
9575 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9576
9577 MockRead data_reads[] = {
9578 // A part of the response body is received with the response headers.
9579 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9580 // The rest of the response body is received in two parts.
9581 MockRead("lo"), MockRead(" world"),
9582 MockRead("junk"), // Should not be read!!
9583 MockRead(SYNCHRONOUS, OK),
9584 };
9585
Ryan Sleevib8d7ea02018-05-07 20:01:019586 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559587 session_deps_.socket_factory->AddSocketDataProvider(&data);
9588
9589 TestCompletionCallback callback;
9590
9591 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9592 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9593
9594 EXPECT_THAT(callback.GetResult(rv), IsOk());
9595
9596 const HttpResponseInfo* response = trans.GetResponseInfo();
9597 ASSERT_TRUE(response);
9598 EXPECT_TRUE(response->headers);
9599 std::string status_line = response->headers->GetStatusLine();
9600 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9601
9602 // Make memory critical notification and ensure the transaction still has been
9603 // operating right.
9604 base::MemoryPressureListener::NotifyMemoryPressure(
9605 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9606 base::RunLoop().RunUntilIdle();
9607
9608 // Socket should not be flushed as long as it is not idle.
9609 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9610
9611 std::string response_data;
9612 rv = ReadTransaction(&trans, &response_data);
9613 EXPECT_THAT(rv, IsOk());
9614 EXPECT_EQ("hello world", response_data);
9615
9616 // Empty the current queue. This is necessary because idle sockets are
9617 // added to the connection pool asynchronously with a PostTask.
9618 base::RunLoop().RunUntilIdle();
9619
9620 // We now check to make sure the socket was added back to the pool.
9621 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9622
9623 // Idle sockets should NOT be flushed on moderate memory pressure.
9624 base::MemoryPressureListener::NotifyMemoryPressure(
9625 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9626 base::RunLoop().RunUntilIdle();
9627
9628 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9629
9630 // Idle sockets should NOT be flushed on critical memory pressure.
9631 base::MemoryPressureListener::NotifyMemoryPressure(
9632 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9633 base::RunLoop().RunUntilIdle();
9634
9635 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9636}
9637
maksim.sisov0adf8592016-07-15 06:25:569638// Grab an SSL socket, use it, and put it back into the pool. Then, make
9639// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019640TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569641 HttpRequestInfo request;
9642 request.method = "GET";
9643 request.url = GURL("https://www.example.org/");
9644 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109645 request.traffic_annotation =
9646 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569647
9648 MockWrite data_writes[] = {
9649 MockWrite("GET / HTTP/1.1\r\n"
9650 "Host: www.example.org\r\n"
9651 "Connection: keep-alive\r\n\r\n"),
9652 };
9653
9654 MockRead data_reads[] = {
9655 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9656 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9657
9658 SSLSocketDataProvider ssl(ASYNC, OK);
9659 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9660
Ryan Sleevib8d7ea02018-05-07 20:01:019661 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569662 session_deps_.socket_factory->AddSocketDataProvider(&data);
9663
9664 TestCompletionCallback callback;
9665
9666 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169667 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569668
Matt Menke9d5e2c92019-02-05 01:42:239669 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569671
9672 EXPECT_THAT(callback.GetResult(rv), IsOk());
9673
bnc691fda62016-08-12 00:43:169674 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569675 ASSERT_TRUE(response);
9676 ASSERT_TRUE(response->headers);
9677 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9678
9679 // Make memory critical notification and ensure the transaction still has been
9680 // operating right.
9681 base::MemoryPressureListener::NotifyMemoryPressure(
9682 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9683 base::RunLoop().RunUntilIdle();
9684
Matt Menke9d5e2c92019-02-05 01:42:239685 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569686
9687 std::string response_data;
bnc691fda62016-08-12 00:43:169688 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569689 EXPECT_THAT(rv, IsOk());
9690 EXPECT_EQ("hello world", response_data);
9691
9692 // Empty the current queue. This is necessary because idle sockets are
9693 // added to the connection pool asynchronously with a PostTask.
9694 base::RunLoop().RunUntilIdle();
9695
9696 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239697 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569698
9699 // Make memory notification once again and ensure idle socket is closed.
9700 base::MemoryPressureListener::NotifyMemoryPressure(
9701 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9702 base::RunLoop().RunUntilIdle();
9703
Matt Menke9d5e2c92019-02-05 01:42:239704 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569705}
9706
[email protected]b4404c02009-04-10 16:38:529707// Make sure that we recycle a socket after a zero-length response.
9708// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019709TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429710 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529711 request.method = "GET";
bncce36dca22015-04-21 22:11:239712 request.url = GURL(
9713 "http://www.example.org/csi?v=3&s=web&action=&"
9714 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9715 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9716 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:109717 request.traffic_annotation =
9718 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529719
danakj1fd259a02016-04-16 03:17:099720 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279721
[email protected]b4404c02009-04-10 16:38:529722 MockRead data_reads[] = {
9723 MockRead("HTTP/1.1 204 No Content\r\n"
9724 "Content-Length: 0\r\n"
9725 "Content-Type: text/html\r\n\r\n"),
9726 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069727 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529728 };
9729
Ryan Sleevib8d7ea02018-05-07 20:01:019730 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079731 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529732
mmenkecc2298e2015-12-07 18:20:189733 // Transaction must be created after the MockReads, so it's destroyed before
9734 // them.
bnc691fda62016-08-12 00:43:169735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189736
[email protected]49639fa2011-12-20 23:22:419737 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529738
tfarina42834112016-09-22 13:38:209739 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019740 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529741
9742 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019743 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529744
bnc691fda62016-08-12 00:43:169745 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529746 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529747
wezca1070932016-05-26 20:30:529748 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529749 std::string status_line = response->headers->GetStatusLine();
9750 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9751
[email protected]90499482013-06-01 00:39:509752 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529753
9754 std::string response_data;
bnc691fda62016-08-12 00:43:169755 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019756 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529757 EXPECT_EQ("", response_data);
9758
9759 // Empty the current queue. This is necessary because idle sockets are
9760 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559761 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529762
9763 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509764 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529765}
9766
bncd16676a2016-07-20 16:23:019767TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099768 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229769 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199770 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229771 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279772
[email protected]1c773ea12009-04-28 19:58:429773 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519774 // Transaction 1: a GET request that succeeds. The socket is recycled
9775 // after use.
9776 request[0].method = "GET";
9777 request[0].url = GURL("http://www.google.com/");
9778 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109779 request[0].traffic_annotation =
9780 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519781 // Transaction 2: a POST request. Reuses the socket kept alive from
9782 // transaction 1. The first attempts fails when writing the POST data.
9783 // This causes the transaction to retry with a new socket. The second
9784 // attempt succeeds.
9785 request[1].method = "POST";
9786 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279787 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519788 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109789 request[1].traffic_annotation =
9790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519791
danakj1fd259a02016-04-16 03:17:099792 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519793
9794 // The first socket is used for transaction 1 and the first attempt of
9795 // transaction 2.
9796
9797 // The response of transaction 1.
9798 MockRead data_reads1[] = {
9799 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9800 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069801 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519802 };
9803 // The mock write results of transaction 1 and the first attempt of
9804 // transaction 2.
9805 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069806 MockWrite(SYNCHRONOUS, 64), // GET
9807 MockWrite(SYNCHRONOUS, 93), // POST
9808 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519809 };
Ryan Sleevib8d7ea02018-05-07 20:01:019810 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519811
9812 // The second socket is used for the second attempt of transaction 2.
9813
9814 // The response of transaction 2.
9815 MockRead data_reads2[] = {
9816 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9817 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069818 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519819 };
9820 // The mock write results of the second attempt of transaction 2.
9821 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069822 MockWrite(SYNCHRONOUS, 93), // POST
9823 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519824 };
Ryan Sleevib8d7ea02018-05-07 20:01:019825 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519826
[email protected]bb88e1d32013-05-03 23:11:079827 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9828 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519829
thestig9d3bb0c2015-01-24 00:49:519830 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519831 "hello world", "welcome"
9832 };
9833
9834 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169835 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519836
[email protected]49639fa2011-12-20 23:22:419837 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519838
tfarina42834112016-09-22 13:38:209839 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019840 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519841
9842 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019843 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519844
bnc691fda62016-08-12 00:43:169845 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529846 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519847
wezca1070932016-05-26 20:30:529848 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519849 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9850
9851 std::string response_data;
bnc691fda62016-08-12 00:43:169852 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019853 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519854 EXPECT_EQ(kExpectedResponseData[i], response_data);
9855 }
9856}
[email protected]f9ee6b52008-11-08 06:46:239857
9858// Test the request-challenge-retry sequence for basic auth when there is
9859// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169860// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019861TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429862 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239863 request.method = "GET";
bncce36dca22015-04-21 22:11:239864 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419865 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109866 request.traffic_annotation =
9867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299868
danakj1fd259a02016-04-16 03:17:099869 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169870 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279871
[email protected]a97cca42009-08-14 01:00:299872 // The password contains an escaped character -- for this test to pass it
9873 // will need to be unescaped by HttpNetworkTransaction.
9874 EXPECT_EQ("b%40r", request.url.password());
9875
[email protected]f9ee6b52008-11-08 06:46:239876 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239877 MockWrite(
9878 "GET / HTTP/1.1\r\n"
9879 "Host: www.example.org\r\n"
9880 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239881 };
9882
9883 MockRead data_reads1[] = {
9884 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9885 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9886 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069887 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239888 };
9889
[email protected]2262e3a2012-05-22 16:08:169890 // After the challenge above, the transaction will be restarted using the
9891 // identity from the url (foo, b@r) to answer the challenge.
9892 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239893 MockWrite(
9894 "GET / HTTP/1.1\r\n"
9895 "Host: www.example.org\r\n"
9896 "Connection: keep-alive\r\n"
9897 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169898 };
9899
9900 MockRead data_reads2[] = {
9901 MockRead("HTTP/1.0 200 OK\r\n"),
9902 MockRead("Content-Length: 100\r\n\r\n"),
9903 MockRead(SYNCHRONOUS, OK),
9904 };
9905
Ryan Sleevib8d7ea02018-05-07 20:01:019906 StaticSocketDataProvider data1(data_reads1, data_writes1);
9907 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079908 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9909 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239910
[email protected]49639fa2011-12-20 23:22:419911 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209912 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239914 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019915 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169916 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169917
9918 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169919 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169921 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019922 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169923 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229924
bnc691fda62016-08-12 00:43:169925 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529926 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169927
9928 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589929 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169930
9931 EXPECT_EQ(100, response->headers->GetContentLength());
9932
9933 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559934 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169935}
9936
9937// Test the request-challenge-retry sequence for basic auth when there is an
9938// incorrect identity in the URL. The identity from the URL should be used only
9939// once.
bncd16676a2016-07-20 16:23:019940TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169941 HttpRequestInfo request;
9942 request.method = "GET";
9943 // Note: the URL has a username:password in it. The password "baz" is
9944 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239945 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169946
9947 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109948 request.traffic_annotation =
9949 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169950
danakj1fd259a02016-04-16 03:17:099951 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169952 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169953
9954 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239955 MockWrite(
9956 "GET / HTTP/1.1\r\n"
9957 "Host: www.example.org\r\n"
9958 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169959 };
9960
9961 MockRead data_reads1[] = {
9962 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9963 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9964 MockRead("Content-Length: 10\r\n\r\n"),
9965 MockRead(SYNCHRONOUS, ERR_FAILED),
9966 };
9967
9968 // After the challenge above, the transaction will be restarted using the
9969 // identity from the url (foo, baz) to answer the challenge.
9970 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239971 MockWrite(
9972 "GET / HTTP/1.1\r\n"
9973 "Host: www.example.org\r\n"
9974 "Connection: keep-alive\r\n"
9975 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169976 };
9977
9978 MockRead data_reads2[] = {
9979 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9980 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9981 MockRead("Content-Length: 10\r\n\r\n"),
9982 MockRead(SYNCHRONOUS, ERR_FAILED),
9983 };
9984
9985 // After the challenge above, the transaction will be restarted using the
9986 // identity supplied by the user (foo, bar) to answer the challenge.
9987 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239988 MockWrite(
9989 "GET / HTTP/1.1\r\n"
9990 "Host: www.example.org\r\n"
9991 "Connection: keep-alive\r\n"
9992 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169993 };
9994
9995 MockRead data_reads3[] = {
9996 MockRead("HTTP/1.0 200 OK\r\n"),
9997 MockRead("Content-Length: 100\r\n\r\n"),
9998 MockRead(SYNCHRONOUS, OK),
9999 };
10000
Ryan Sleevib8d7ea02018-05-07 20:01:0110001 StaticSocketDataProvider data1(data_reads1, data_writes1);
10002 StaticSocketDataProvider data2(data_reads2, data_writes2);
10003 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710004 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10005 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10006 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:1610007
10008 TestCompletionCallback callback1;
10009
tfarina42834112016-09-22 13:38:2010010 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:1610012
10013 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110014 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:1610015
bnc691fda62016-08-12 00:43:1610016 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:1610017 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610018 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110019 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:1610020 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110021 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610022 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:1610023
bnc691fda62016-08-12 00:43:1610024 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210025 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810026 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:1610027
10028 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1610029 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:0110030 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:1610031 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110032 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610033 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:1610034
bnc691fda62016-08-12 00:43:1610035 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210036 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:1610037
10038 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:5810039 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:1610040
10041 EXPECT_EQ(100, response->headers->GetContentLength());
10042
[email protected]ea9dc9a2009-09-05 00:43:3210043 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:5510044 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:3210045}
10046
[email protected]2217aa22013-10-11 03:03:5410047
10048// Test the request-challenge-retry sequence for basic auth when there is a
10049// correct identity in the URL, but its use is being suppressed. The identity
10050// from the URL should never be used.
bncd16676a2016-07-20 16:23:0110051TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:5410052 HttpRequestInfo request;
10053 request.method = "GET";
bncce36dca22015-04-21 22:11:2310054 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:5410055 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:1010056 request.traffic_annotation =
10057 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:5410058
danakj1fd259a02016-04-16 03:17:0910059 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610060 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:5410061
10062 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310063 MockWrite(
10064 "GET / HTTP/1.1\r\n"
10065 "Host: www.example.org\r\n"
10066 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:5410067 };
10068
10069 MockRead data_reads1[] = {
10070 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10071 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10072 MockRead("Content-Length: 10\r\n\r\n"),
10073 MockRead(SYNCHRONOUS, ERR_FAILED),
10074 };
10075
10076 // After the challenge above, the transaction will be restarted using the
10077 // identity supplied by the user, not the one in the URL, to answer the
10078 // challenge.
10079 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310080 MockWrite(
10081 "GET / HTTP/1.1\r\n"
10082 "Host: www.example.org\r\n"
10083 "Connection: keep-alive\r\n"
10084 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:5410085 };
10086
10087 MockRead data_reads3[] = {
10088 MockRead("HTTP/1.0 200 OK\r\n"),
10089 MockRead("Content-Length: 100\r\n\r\n"),
10090 MockRead(SYNCHRONOUS, OK),
10091 };
10092
Ryan Sleevib8d7ea02018-05-07 20:01:0110093 StaticSocketDataProvider data1(data_reads1, data_writes1);
10094 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:5410095 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10096 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10097
10098 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2010099 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110100 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410101 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110102 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610103 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410104
bnc691fda62016-08-12 00:43:1610105 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210106 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810107 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:5410108
10109 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1610110 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:0110111 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410112 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110113 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610114 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410115
bnc691fda62016-08-12 00:43:1610116 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210117 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:5410118
10119 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:5810120 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:5410121 EXPECT_EQ(100, response->headers->GetContentLength());
10122
10123 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:5510124 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:5410125}
10126
[email protected]f9ee6b52008-11-08 06:46:2310127// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:0110128TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:0910129 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:2310130
10131 // Transaction 1: authenticate (foo, bar) on MyRealm1
10132 {
[email protected]1c773ea12009-04-28 19:58:4210133 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310134 request.method = "GET";
bncce36dca22015-04-21 22:11:2310135 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010136 request.traffic_annotation =
10137 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310138
bnc691fda62016-08-12 00:43:1610139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710140
[email protected]f9ee6b52008-11-08 06:46:2310141 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310142 MockWrite(
10143 "GET /x/y/z HTTP/1.1\r\n"
10144 "Host: www.example.org\r\n"
10145 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310146 };
10147
10148 MockRead data_reads1[] = {
10149 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10150 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10151 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610152 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310153 };
10154
10155 // Resend with authorization (username=foo, password=bar)
10156 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310157 MockWrite(
10158 "GET /x/y/z HTTP/1.1\r\n"
10159 "Host: www.example.org\r\n"
10160 "Connection: keep-alive\r\n"
10161 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310162 };
10163
10164 // Sever accepts the authorization.
10165 MockRead data_reads2[] = {
10166 MockRead("HTTP/1.0 200 OK\r\n"),
10167 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610168 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310169 };
10170
Ryan Sleevib8d7ea02018-05-07 20:01:0110171 StaticSocketDataProvider data1(data_reads1, data_writes1);
10172 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710173 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10174 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310175
[email protected]49639fa2011-12-20 23:22:4110176 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310177
tfarina42834112016-09-22 13:38:2010178 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110179 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310180
10181 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110182 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310183
bnc691fda62016-08-12 00:43:1610184 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210185 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810186 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310187
[email protected]49639fa2011-12-20 23:22:4110188 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310189
bnc691fda62016-08-12 00:43:1610190 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10191 callback2.callback());
robpercival214763f2016-07-01 23:27:0110192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310193
10194 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110195 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310196
bnc691fda62016-08-12 00:43:1610197 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210198 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810199 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310200 EXPECT_EQ(100, response->headers->GetContentLength());
10201 }
10202
10203 // ------------------------------------------------------------------------
10204
10205 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
10206 {
[email protected]1c773ea12009-04-28 19:58:4210207 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310208 request.method = "GET";
10209 // Note that Transaction 1 was at /x/y/z, so this is in the same
10210 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:2310211 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010212 request.traffic_annotation =
10213 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310214
bnc691fda62016-08-12 00:43:1610215 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710216
[email protected]f9ee6b52008-11-08 06:46:2310217 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310218 MockWrite(
10219 "GET /x/y/a/b HTTP/1.1\r\n"
10220 "Host: www.example.org\r\n"
10221 "Connection: keep-alive\r\n"
10222 // Send preemptive authorization for MyRealm1
10223 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310224 };
10225
10226 // The server didn't like the preemptive authorization, and
10227 // challenges us for a different realm (MyRealm2).
10228 MockRead data_reads1[] = {
10229 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10230 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
10231 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610232 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310233 };
10234
10235 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
10236 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310237 MockWrite(
10238 "GET /x/y/a/b HTTP/1.1\r\n"
10239 "Host: www.example.org\r\n"
10240 "Connection: keep-alive\r\n"
10241 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310242 };
10243
10244 // Sever accepts the authorization.
10245 MockRead data_reads2[] = {
10246 MockRead("HTTP/1.0 200 OK\r\n"),
10247 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610248 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310249 };
10250
Ryan Sleevib8d7ea02018-05-07 20:01:0110251 StaticSocketDataProvider data1(data_reads1, data_writes1);
10252 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710253 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10254 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310255
[email protected]49639fa2011-12-20 23:22:4110256 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310257
tfarina42834112016-09-22 13:38:2010258 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110259 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310260
10261 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110262 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310263
bnc691fda62016-08-12 00:43:1610264 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210265 ASSERT_TRUE(response);
10266 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:0410267 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:4310268 EXPECT_EQ("http://www.example.org",
10269 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0410270 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:1910271 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:2310272
[email protected]49639fa2011-12-20 23:22:4110273 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310274
bnc691fda62016-08-12 00:43:1610275 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
10276 callback2.callback());
robpercival214763f2016-07-01 23:27:0110277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310278
10279 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110280 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310281
bnc691fda62016-08-12 00:43:1610282 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210283 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810284 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310285 EXPECT_EQ(100, response->headers->GetContentLength());
10286 }
10287
10288 // ------------------------------------------------------------------------
10289
10290 // Transaction 3: Resend a request in MyRealm's protection space --
10291 // succeed with preemptive authorization.
10292 {
[email protected]1c773ea12009-04-28 19:58:4210293 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310294 request.method = "GET";
bncce36dca22015-04-21 22:11:2310295 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:1010296 request.traffic_annotation =
10297 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310298
bnc691fda62016-08-12 00:43:1610299 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710300
[email protected]f9ee6b52008-11-08 06:46:2310301 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310302 MockWrite(
10303 "GET /x/y/z2 HTTP/1.1\r\n"
10304 "Host: www.example.org\r\n"
10305 "Connection: keep-alive\r\n"
10306 // The authorization for MyRealm1 gets sent preemptively
10307 // (since the url is in the same protection space)
10308 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310309 };
10310
10311 // Sever accepts the preemptive authorization
10312 MockRead data_reads1[] = {
10313 MockRead("HTTP/1.0 200 OK\r\n"),
10314 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610315 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310316 };
10317
Ryan Sleevib8d7ea02018-05-07 20:01:0110318 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710319 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:2310320
[email protected]49639fa2011-12-20 23:22:4110321 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310322
tfarina42834112016-09-22 13:38:2010323 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110324 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310325
10326 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110327 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310328
bnc691fda62016-08-12 00:43:1610329 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210330 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:2310331
Emily Starkf2c9bbd2019-04-09 17:08:5810332 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310333 EXPECT_EQ(100, response->headers->GetContentLength());
10334 }
10335
10336 // ------------------------------------------------------------------------
10337
10338 // Transaction 4: request another URL in MyRealm (however the
10339 // url is not known to belong to the protection space, so no pre-auth).
10340 {
[email protected]1c773ea12009-04-28 19:58:4210341 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310342 request.method = "GET";
bncce36dca22015-04-21 22:11:2310343 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:1010344 request.traffic_annotation =
10345 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310346
bnc691fda62016-08-12 00:43:1610347 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710348
[email protected]f9ee6b52008-11-08 06:46:2310349 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310350 MockWrite(
10351 "GET /x/1 HTTP/1.1\r\n"
10352 "Host: www.example.org\r\n"
10353 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310354 };
10355
10356 MockRead data_reads1[] = {
10357 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10358 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10359 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610360 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310361 };
10362
10363 // Resend with authorization from MyRealm's cache.
10364 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310365 MockWrite(
10366 "GET /x/1 HTTP/1.1\r\n"
10367 "Host: www.example.org\r\n"
10368 "Connection: keep-alive\r\n"
10369 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310370 };
10371
10372 // Sever accepts the authorization.
10373 MockRead data_reads2[] = {
10374 MockRead("HTTP/1.0 200 OK\r\n"),
10375 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610376 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310377 };
10378
Ryan Sleevib8d7ea02018-05-07 20:01:0110379 StaticSocketDataProvider data1(data_reads1, data_writes1);
10380 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710381 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10382 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310383
[email protected]49639fa2011-12-20 23:22:4110384 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310385
tfarina42834112016-09-22 13:38:2010386 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110387 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310388
10389 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110390 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310391
bnc691fda62016-08-12 00:43:1610392 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110393 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610394 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210396 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110397 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610398 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210399
bnc691fda62016-08-12 00:43:1610400 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210401 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810402 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310403 EXPECT_EQ(100, response->headers->GetContentLength());
10404 }
10405
10406 // ------------------------------------------------------------------------
10407
10408 // Transaction 5: request a URL in MyRealm, but the server rejects the
10409 // cached identity. Should invalidate and re-prompt.
10410 {
[email protected]1c773ea12009-04-28 19:58:4210411 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310412 request.method = "GET";
bncce36dca22015-04-21 22:11:2310413 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:1010414 request.traffic_annotation =
10415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310416
bnc691fda62016-08-12 00:43:1610417 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710418
[email protected]f9ee6b52008-11-08 06:46:2310419 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310420 MockWrite(
10421 "GET /p/q/t HTTP/1.1\r\n"
10422 "Host: www.example.org\r\n"
10423 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310424 };
10425
10426 MockRead data_reads1[] = {
10427 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10428 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10429 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610430 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310431 };
10432
10433 // Resend with authorization from cache for MyRealm.
10434 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310435 MockWrite(
10436 "GET /p/q/t HTTP/1.1\r\n"
10437 "Host: www.example.org\r\n"
10438 "Connection: keep-alive\r\n"
10439 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310440 };
10441
10442 // Sever rejects the authorization.
10443 MockRead data_reads2[] = {
10444 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10445 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10446 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610447 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310448 };
10449
10450 // At this point we should prompt for new credentials for MyRealm.
10451 // Restart with username=foo3, password=foo4.
10452 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310453 MockWrite(
10454 "GET /p/q/t HTTP/1.1\r\n"
10455 "Host: www.example.org\r\n"
10456 "Connection: keep-alive\r\n"
10457 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310458 };
10459
10460 // Sever accepts the authorization.
10461 MockRead data_reads3[] = {
10462 MockRead("HTTP/1.0 200 OK\r\n"),
10463 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610464 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310465 };
10466
Ryan Sleevib8d7ea02018-05-07 20:01:0110467 StaticSocketDataProvider data1(data_reads1, data_writes1);
10468 StaticSocketDataProvider data2(data_reads2, data_writes2);
10469 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10471 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10472 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:2310473
[email protected]49639fa2011-12-20 23:22:4110474 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310475
tfarina42834112016-09-22 13:38:2010476 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310478
10479 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110480 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310481
bnc691fda62016-08-12 00:43:1610482 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110483 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610484 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210486 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110487 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610488 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210489
bnc691fda62016-08-12 00:43:1610490 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210491 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810492 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310493
[email protected]49639fa2011-12-20 23:22:4110494 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:2310495
bnc691fda62016-08-12 00:43:1610496 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
10497 callback3.callback());
robpercival214763f2016-07-01 23:27:0110498 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310499
[email protected]0757e7702009-03-27 04:00:2210500 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110501 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310502
bnc691fda62016-08-12 00:43:1610503 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210504 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810505 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310506 EXPECT_EQ(100, response->headers->GetContentLength());
10507 }
10508}
[email protected]89ceba9a2009-03-21 03:46:0610509
[email protected]3c32c5f2010-05-18 15:18:1210510// Tests that nonce count increments when multiple auth attempts
10511// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110512TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410513 HttpAuthHandlerDigest::Factory* digest_factory =
10514 new HttpAuthHandlerDigest::Factory();
10515 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10516 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10517 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710518 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210520
10521 // Transaction 1: authenticate (foo, bar) on MyRealm1
10522 {
[email protected]3c32c5f2010-05-18 15:18:1210523 HttpRequestInfo request;
10524 request.method = "GET";
bncce36dca22015-04-21 22:11:2310525 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010526 request.traffic_annotation =
10527 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210528
bnc691fda62016-08-12 00:43:1610529 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710530
[email protected]3c32c5f2010-05-18 15:18:1210531 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310532 MockWrite(
10533 "GET /x/y/z HTTP/1.1\r\n"
10534 "Host: www.example.org\r\n"
10535 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210536 };
10537
10538 MockRead data_reads1[] = {
10539 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10540 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10541 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610542 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210543 };
10544
10545 // Resend with authorization (username=foo, password=bar)
10546 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310547 MockWrite(
10548 "GET /x/y/z HTTP/1.1\r\n"
10549 "Host: www.example.org\r\n"
10550 "Connection: keep-alive\r\n"
10551 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10552 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10553 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10554 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210555 };
10556
10557 // Sever accepts the authorization.
10558 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810559 MockRead("HTTP/1.0 200 OK\r\n"),
10560 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210561 };
10562
Ryan Sleevib8d7ea02018-05-07 20:01:0110563 StaticSocketDataProvider data1(data_reads1, data_writes1);
10564 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710565 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10566 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210567
[email protected]49639fa2011-12-20 23:22:4110568 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210569
tfarina42834112016-09-22 13:38:2010570 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110571 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210572
10573 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110574 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210575
bnc691fda62016-08-12 00:43:1610576 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210577 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810578 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210579
[email protected]49639fa2011-12-20 23:22:4110580 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210581
bnc691fda62016-08-12 00:43:1610582 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10583 callback2.callback());
robpercival214763f2016-07-01 23:27:0110584 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210585
10586 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110587 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210588
bnc691fda62016-08-12 00:43:1610589 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210590 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810591 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210592 }
10593
10594 // ------------------------------------------------------------------------
10595
10596 // Transaction 2: Request another resource in digestive's protection space.
10597 // This will preemptively add an Authorization header which should have an
10598 // "nc" value of 2 (as compared to 1 in the first use.
10599 {
[email protected]3c32c5f2010-05-18 15:18:1210600 HttpRequestInfo request;
10601 request.method = "GET";
10602 // Note that Transaction 1 was at /x/y/z, so this is in the same
10603 // protection space as digest.
bncce36dca22015-04-21 22:11:2310604 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010605 request.traffic_annotation =
10606 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210607
bnc691fda62016-08-12 00:43:1610608 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710609
[email protected]3c32c5f2010-05-18 15:18:1210610 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310611 MockWrite(
10612 "GET /x/y/a/b HTTP/1.1\r\n"
10613 "Host: www.example.org\r\n"
10614 "Connection: keep-alive\r\n"
10615 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10616 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10617 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10618 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210619 };
10620
10621 // Sever accepts the authorization.
10622 MockRead data_reads1[] = {
10623 MockRead("HTTP/1.0 200 OK\r\n"),
10624 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610625 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210626 };
10627
Ryan Sleevib8d7ea02018-05-07 20:01:0110628 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710629 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210630
[email protected]49639fa2011-12-20 23:22:4110631 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210632
tfarina42834112016-09-22 13:38:2010633 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110634 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210635
10636 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110637 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210638
bnc691fda62016-08-12 00:43:1610639 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210640 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810641 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210642 }
10643}
10644
[email protected]89ceba9a2009-03-21 03:46:0610645// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110646TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610647 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910648 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610649 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610650
10651 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410652 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610653 trans.read_buf_len_ = 15;
10654 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610655
10656 // Setup state in response_
bnc691fda62016-08-12 00:43:1610657 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810658 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810659 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710660 response->response_time = base::Time::Now();
10661 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610662
10663 { // Setup state for response_.vary_data
10664 HttpRequestInfo request;
10665 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10666 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710667 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310668 request.extra_headers.SetHeader("Foo", "1");
10669 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010670 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610671 }
10672
10673 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610674 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610675
10676 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610677 EXPECT_FALSE(trans.read_buf_);
10678 EXPECT_EQ(0, trans.read_buf_len_);
10679 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810680 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210681 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410682 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810683 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710684 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610685}
10686
[email protected]bacff652009-03-31 17:50:3310687// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110688TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310689 HttpRequestInfo request;
10690 request.method = "GET";
bncce36dca22015-04-21 22:11:2310691 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010692 request.traffic_annotation =
10693 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310694
danakj1fd259a02016-04-16 03:17:0910695 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610696 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710697
[email protected]bacff652009-03-31 17:50:3310698 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310699 MockWrite(
10700 "GET / HTTP/1.1\r\n"
10701 "Host: www.example.org\r\n"
10702 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310703 };
10704
10705 MockRead data_reads[] = {
10706 MockRead("HTTP/1.0 200 OK\r\n"),
10707 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10708 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610709 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310710 };
10711
[email protected]5ecc992a42009-11-11 01:41:5910712 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110713 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610714 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10715 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310716
[email protected]bb88e1d32013-05-03 23:11:0710717 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10718 session_deps_.socket_factory->AddSocketDataProvider(&data);
10719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10720 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310721
[email protected]49639fa2011-12-20 23:22:4110722 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310723
tfarina42834112016-09-22 13:38:2010724 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310726
10727 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110728 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310729
bnc691fda62016-08-12 00:43:1610730 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310732
10733 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110734 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310735
bnc691fda62016-08-12 00:43:1610736 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310737
wezca1070932016-05-26 20:30:5210738 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310739 EXPECT_EQ(100, response->headers->GetContentLength());
10740}
10741
10742// Test HTTPS connections to a site with a bad certificate, going through a
10743// proxy
bncd16676a2016-07-20 16:23:0110744TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610745 session_deps_.proxy_resolution_service =
10746 ConfiguredProxyResolutionService::CreateFixed(
10747 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310748
10749 HttpRequestInfo request;
10750 request.method = "GET";
bncce36dca22015-04-21 22:11:2310751 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010752 request.traffic_annotation =
10753 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310754
10755 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710756 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10757 "Host: www.example.org:443\r\n"
10758 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310759 };
10760
10761 MockRead proxy_reads[] = {
10762 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610763 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310764 };
10765
10766 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710767 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10768 "Host: www.example.org:443\r\n"
10769 "Proxy-Connection: keep-alive\r\n\r\n"),
10770 MockWrite("GET / HTTP/1.1\r\n"
10771 "Host: www.example.org\r\n"
10772 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310773 };
10774
10775 MockRead data_reads[] = {
10776 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10777 MockRead("HTTP/1.0 200 OK\r\n"),
10778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10779 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610780 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310781 };
10782
Ryan Sleevib8d7ea02018-05-07 20:01:0110783 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10784 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610785 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10786 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310787
[email protected]bb88e1d32013-05-03 23:11:0710788 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10789 session_deps_.socket_factory->AddSocketDataProvider(&data);
10790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310792
[email protected]49639fa2011-12-20 23:22:4110793 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310794
10795 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710796 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310797
danakj1fd259a02016-04-16 03:17:0910798 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610799 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310800
tfarina42834112016-09-22 13:38:2010801 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110802 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310803
10804 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110805 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310806
bnc691fda62016-08-12 00:43:1610807 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110808 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310809
10810 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110811 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310812
bnc691fda62016-08-12 00:43:1610813 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310814
wezca1070932016-05-26 20:30:5210815 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310816 EXPECT_EQ(100, response->headers->GetContentLength());
10817 }
10818}
10819
[email protected]2df19bb2010-08-25 20:13:4610820
10821// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110822TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910823 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610824 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910825 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410826 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710827 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610828
10829 HttpRequestInfo request;
10830 request.method = "GET";
bncce36dca22015-04-21 22:11:2310831 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010832 request.traffic_annotation =
10833 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610834
10835 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710836 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10837 "Host: www.example.org:443\r\n"
10838 "Proxy-Connection: keep-alive\r\n\r\n"),
10839 MockWrite("GET / HTTP/1.1\r\n"
10840 "Host: www.example.org\r\n"
10841 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610842 };
10843
10844 MockRead data_reads[] = {
10845 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10846 MockRead("HTTP/1.1 200 OK\r\n"),
10847 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10848 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610849 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610850 };
10851
Ryan Sleevib8d7ea02018-05-07 20:01:0110852 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610853 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10854 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610855
[email protected]bb88e1d32013-05-03 23:11:0710856 session_deps_.socket_factory->AddSocketDataProvider(&data);
10857 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10858 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610859
[email protected]49639fa2011-12-20 23:22:4110860 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610861
danakj1fd259a02016-04-16 03:17:0910862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610863 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610864
tfarina42834112016-09-22 13:38:2010865 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110866 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610867
10868 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110869 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610870 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610871
wezca1070932016-05-26 20:30:5210872 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610873
tbansal2ecbbc72016-10-06 17:15:4710874 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610875 EXPECT_TRUE(response->headers->IsKeepAlive());
10876 EXPECT_EQ(200, response->headers->response_code());
10877 EXPECT_EQ(100, response->headers->GetContentLength());
10878 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010879
10880 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610881 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010882 TestLoadTimingNotReusedWithPac(load_timing_info,
10883 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610884}
10885
Eric Roman695a7872019-04-16 21:53:2910886// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110887TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910888 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610889 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910890 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410891 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710892 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910893
Matt Menkeecfecfc72019-02-05 19:15:2810894 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10895 session_deps_.host_resolver->set_ondemand_mode(true);
10896
[email protected]511f6f52010-12-17 03:58:2910897 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210898 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910899 request.method = "GET";
bncce36dca22015-04-21 22:11:2310900 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010901 request.traffic_annotation =
10902 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910903
10904 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810905 MockWrite(ASYNC, 0,
10906 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710907 "Host: www.example.org:443\r\n"
10908 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910909 };
10910
10911 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810912 // Pause on first read.
10913 MockRead(ASYNC, ERR_IO_PENDING, 1),
10914 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10915 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10916 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910917 };
10918
Matt Menkeecfecfc72019-02-05 19:15:2810919 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610920 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910921
[email protected]bb88e1d32013-05-03 23:11:0710922 session_deps_.socket_factory->AddSocketDataProvider(&data);
10923 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910924
[email protected]49639fa2011-12-20 23:22:4110925 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910926
danakj1fd259a02016-04-16 03:17:0910927 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610928 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910929
tfarina42834112016-09-22 13:38:2010930 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810932 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10933
10934 // Host resolution takes |kTimeIncrement|.
10935 FastForwardBy(kTimeIncrement);
10936 // Resolving the current request with |ResolveNow| will cause the pending
10937 // request to instantly complete, and the async connect will start as well.
10938 session_deps_.host_resolver->ResolveOnlyRequestNow();
10939
10940 // Connecting takes |kTimeIncrement|.
10941 FastForwardBy(kTimeIncrement);
10942 data.RunUntilPaused();
10943
10944 // The server takes |kTimeIncrement| to respond.
10945 FastForwardBy(kTimeIncrement);
10946 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910947
10948 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910949 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910950}
10951
Eric Roman74103c72019-02-21 00:23:1210952// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10953TEST_F(HttpNetworkTransactionTest,
10954 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10955 base::HistogramTester histograms;
10956 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610957 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Eric Roman74103c72019-02-21 00:23:1210958 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410959 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210960 session_deps_.net_log = &net_log;
10961
10962 HttpRequestInfo request;
10963 request.method = "GET";
10964 request.url = GURL("https://www.example.org/");
10965 request.traffic_annotation =
10966 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10967
10968 MockWrite data_writes[] = {
10969 MockWrite(ASYNC, 0,
10970 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10971 "Host: www.example.org:443\r\n"
10972 "Proxy-Connection: keep-alive\r\n\r\n"),
10973 };
10974
10975 MockRead data_reads[] = {
10976 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10977 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10978 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10979 };
10980
10981 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10982 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10983
10984 session_deps_.socket_factory->AddSocketDataProvider(&data);
10985 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10986
10987 TestCompletionCallback callback;
10988
10989 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10990 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10991
10992 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10993 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10994
10995 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910996 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210997}
10998
10999// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
11000// request for main frames.
11001TEST_F(HttpNetworkTransactionTest,
11002 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
11003 base::HistogramTester histograms;
11004 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611005 ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
Eric Roman74103c72019-02-21 00:23:1211006 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411007 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1211008 session_deps_.net_log = &net_log;
11009
11010 HttpRequestInfo request;
11011 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
11012 request.method = "GET";
11013 request.url = GURL("https://www.example.org/");
11014 request.traffic_annotation =
11015 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11016
11017 MockWrite data_writes[] = {
11018 MockWrite(ASYNC, 0,
11019 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11020 "Host: www.example.org:443\r\n"
11021 "Proxy-Connection: keep-alive\r\n\r\n"),
11022 };
11023
11024 MockRead data_reads[] = {
11025 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
11026 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
11027 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
11028 };
11029
11030 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
11031 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
11032
11033 session_deps_.socket_factory->AddSocketDataProvider(&data);
11034 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
11035
11036 TestCompletionCallback callback;
11037
11038 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11040
11041 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11043
11044 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5911045 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1211046}
11047
Eric Roman695a7872019-04-16 21:53:2911048// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1211049// frames.
bncd16676a2016-07-20 16:23:0111050TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1211051 base::HistogramTester histograms;
Nicolas Arciniegad2013f92020-02-07 23:00:5611052 session_deps_.proxy_resolution_service =
11053 ConfiguredProxyResolutionService::CreateFixed(
11054 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411055 RecordingTestNetLog net_log;
Matt Menkeecfecfc72019-02-05 19:15:2811056 session_deps_.net_log = &net_log;
11057
Matt Menkeecfecfc72019-02-05 19:15:2811058 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
11059 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2911060
11061 HttpRequestInfo request;
11062 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1211063 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2311064 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011065 request.traffic_annotation =
11066 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911067
Ryan Hamilton0239aac2018-05-19 00:03:1311068 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411069 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11070 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311071 spdy::SpdySerializedFrame goaway(
11072 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2911073 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111074 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2811075 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2911076 };
11077
11078 static const char* const kExtraHeaders[] = {
11079 "location",
11080 "http://login.example.com/",
11081 };
Ryan Hamilton0239aac2018-05-19 00:03:1311082 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411083 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2911084 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2811085 // Pause on first read.
11086 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
11087 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2911088 };
11089
Matt Menkeecfecfc72019-02-05 19:15:2811090 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611091 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3611092 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2911093
[email protected]bb88e1d32013-05-03 23:11:0711094 session_deps_.socket_factory->AddSocketDataProvider(&data);
11095 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911096
[email protected]49639fa2011-12-20 23:22:4111097 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911098
danakj1fd259a02016-04-16 03:17:0911099 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611100 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911101
tfarina42834112016-09-22 13:38:2011102 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111103 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2811104 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2911105
Matt Menkeecfecfc72019-02-05 19:15:2811106 // Host resolution takes |kTimeIncrement|.
11107 FastForwardBy(kTimeIncrement);
11108 // Resolving the current request with |ResolveNow| will cause the pending
11109 // request to instantly complete, and the async connect will start as well.
11110 session_deps_.host_resolver->ResolveOnlyRequestNow();
11111
11112 // Connecting takes |kTimeIncrement|.
11113 FastForwardBy(kTimeIncrement);
11114 data.RunUntilPaused();
11115
11116 FastForwardBy(kTimeIncrement);
11117 data.Resume();
[email protected]511f6f52010-12-17 03:58:2911118 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5911119 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911120}
11121
[email protected]4eddbc732012-08-09 05:40:1711122// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111123TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611124 session_deps_.proxy_resolution_service =
11125 ConfiguredProxyResolutionService::CreateFixed(
11126 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911127
11128 HttpRequestInfo request;
11129 request.method = "GET";
bncce36dca22015-04-21 22:11:2311130 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011131 request.traffic_annotation =
11132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911133
11134 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711135 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11136 "Host: www.example.org:443\r\n"
11137 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2911138 };
11139
11140 MockRead data_reads[] = {
11141 MockRead("HTTP/1.1 404 Not Found\r\n"),
11142 MockRead("Content-Length: 23\r\n\r\n"),
11143 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0611144 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2911145 };
11146
Ryan Sleevib8d7ea02018-05-07 20:01:0111147 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611148 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2911149
[email protected]bb88e1d32013-05-03 23:11:0711150 session_deps_.socket_factory->AddSocketDataProvider(&data);
11151 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911152
[email protected]49639fa2011-12-20 23:22:4111153 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911154
danakj1fd259a02016-04-16 03:17:0911155 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611156 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911157
tfarina42834112016-09-22 13:38:2011158 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111159 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911160
11161 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111162 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911163
ttuttle960fcbf2016-04-19 13:26:3211164 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911165}
11166
[email protected]4eddbc732012-08-09 05:40:1711167// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111168TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611169 session_deps_.proxy_resolution_service =
11170 ConfiguredProxyResolutionService::CreateFixed(
11171 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911172
11173 HttpRequestInfo request;
11174 request.method = "GET";
bncce36dca22015-04-21 22:11:2311175 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011176 request.traffic_annotation =
11177 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911178
Ryan Hamilton0239aac2018-05-19 00:03:1311179 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411180 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11181 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311182 spdy::SpdySerializedFrame rst(
11183 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2911184 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111185 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2911186 };
11187
11188 static const char* const kExtraHeaders[] = {
11189 "location",
11190 "http://login.example.com/",
11191 };
Ryan Hamilton0239aac2018-05-19 00:03:1311192 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411193 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1311194 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1911195 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2911196 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111197 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1311198 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2911199 };
11200
Ryan Sleevib8d7ea02018-05-07 20:01:0111201 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611202 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3611203 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2911204
[email protected]bb88e1d32013-05-03 23:11:0711205 session_deps_.socket_factory->AddSocketDataProvider(&data);
11206 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911207
[email protected]49639fa2011-12-20 23:22:4111208 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911209
danakj1fd259a02016-04-16 03:17:0911210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611211 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911212
tfarina42834112016-09-22 13:38:2011213 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111214 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911215
11216 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111217 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911218
ttuttle960fcbf2016-04-19 13:26:3211219 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911220}
11221
[email protected]0c5fb722012-02-28 11:50:3511222// Test the request-challenge-retry sequence for basic auth, through
11223// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0111224TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3511225 HttpRequestInfo request;
11226 request.method = "GET";
bncce36dca22015-04-21 22:11:2311227 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3511228 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:0011229 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:1011230 request.traffic_annotation =
11231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3511232
11233 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5911234 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611235 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911236 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411237 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711238 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0911239 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3511240
11241 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1311242 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411243 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11244 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311245 spdy::SpdySerializedFrame rst(
11246 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3811247 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3511248
bnc691fda62016-08-12 00:43:1611249 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3511250 // be issuing -- the final header line contains the credentials.
11251 const char* const kAuthCredentials[] = {
11252 "proxy-authorization", "Basic Zm9vOmJhcg==",
11253 };
Ryan Hamilton0239aac2018-05-19 00:03:1311254 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411255 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
11256 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2311257 HostPortPair("www.example.org", 443)));
11258 // fetch https://www.example.org/ via HTTP
11259 const char get[] =
11260 "GET / HTTP/1.1\r\n"
11261 "Host: www.example.org\r\n"
11262 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1311263 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1911264 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3511265
11266 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111267 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
11268 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3511269 };
11270
11271 // The proxy responds to the connect with a 407, using a persistent
11272 // connection.
thestig9d3bb0c2015-01-24 00:49:5111273 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3511274 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3511275 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
11276 };
Ryan Hamilton0239aac2018-05-19 00:03:1311277 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411278 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3511279
Ryan Hamilton0239aac2018-05-19 00:03:1311280 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3511281 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3511282 const char resp[] = "HTTP/1.1 200 OK\r\n"
11283 "Content-Length: 5\r\n\r\n";
11284
Ryan Hamilton0239aac2018-05-19 00:03:1311285 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1911286 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1311287 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1911288 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3511289 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111290 CreateMockRead(conn_auth_resp, 1, ASYNC),
11291 CreateMockRead(conn_resp, 4, ASYNC),
11292 CreateMockRead(wrapped_get_resp, 6, ASYNC),
11293 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1311294 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3511295 };
11296
Ryan Sleevib8d7ea02018-05-07 20:01:0111297 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711298 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3511299 // Negotiate SPDY to the proxy
11300 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611301 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711302 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3511303 // Vanilla SSL to the server
11304 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711305 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3511306
11307 TestCompletionCallback callback1;
11308
bnc87dcefc2017-05-25 12:47:5811309 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911310 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3511311
11312 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111313 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511314
11315 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111316 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5411317 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3511318 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0011319 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11320 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511321 ExpectLogContainsSomewhere(
11322 entries, pos,
mikecirone8b85c432016-09-08 19:11:0011323 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11324 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511325
11326 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211327 ASSERT_TRUE(response);
11328 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3511329 EXPECT_EQ(407, response->headers->response_code());
11330 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5811331 EXPECT_TRUE(response->auth_challenge.has_value());
11332 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3511333
11334 TestCompletionCallback callback2;
11335
11336 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
11337 callback2.callback());
robpercival214763f2016-07-01 23:27:0111338 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511339
11340 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111341 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3511342
11343 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211344 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3511345
11346 EXPECT_TRUE(response->headers->IsKeepAlive());
11347 EXPECT_EQ(200, response->headers->response_code());
11348 EXPECT_EQ(5, response->headers->GetContentLength());
11349 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11350
11351 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5811352 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3511353
[email protected]029c83b62013-01-24 05:28:2011354 LoadTimingInfo load_timing_info;
11355 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11356 TestLoadTimingNotReusedWithPac(load_timing_info,
11357 CONNECT_TIMING_HAS_SSL_TIMES);
11358
[email protected]0c5fb722012-02-28 11:50:3511359 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111360 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]0c5fb722012-02-28 11:50:3511361}
11362
[email protected]7c6f7ba2012-04-03 04:09:2911363// Test that an explicitly trusted SPDY proxy can push a resource from an
11364// origin that is different from that of its associated resource.
Matt Menkedf93ff72020-07-16 02:23:0311365TEST_F(HttpNetworkTransactionTest, CrossOriginSpdyProxyPush) {
tbansal28e68f82016-02-04 02:56:1511366 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911367 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511368 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11369 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2911370 HttpRequestInfo request;
11371 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1011372 request.traffic_annotation =
11373 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911374
[email protected]7c6f7ba2012-04-03 04:09:2911375 request.method = "GET";
bncce36dca22015-04-21 22:11:2311376 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2911377 push_request.method = "GET";
11378 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1011379 push_request.traffic_annotation =
11380 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911381
tbansal28e68f82016-02-04 02:56:1511382 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5911383 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611384 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911385 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411386 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711387 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011388
Eric Roman3d8546a2018-09-10 17:00:5211389 session_deps_.proxy_resolution_service->SetProxyDelegate(
11390 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011391
danakj1fd259a02016-04-16 03:17:0911392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2911393
Ryan Hamilton0239aac2018-05-19 00:03:1311394 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511395 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311396 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511397 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2911398
11399 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111400 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511401 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2911402 };
11403
Ryan Hamilton0239aac2018-05-19 00:03:1311404 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511405 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3611406
Ryan Hamilton0239aac2018-05-19 00:03:1311407 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511408 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2911409
Ryan Hamilton0239aac2018-05-19 00:03:1311410 spdy::SpdySerializedFrame stream1_body(
11411 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2911412
Ryan Hamilton0239aac2018-05-19 00:03:1311413 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1911414 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2911415
11416 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3611417 CreateMockRead(stream2_syn, 1, ASYNC),
11418 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511419 CreateMockRead(stream1_body, 4, ASYNC),
11420 CreateMockRead(stream2_body, 5, ASYNC),
11421 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2911422 };
11423
Ryan Sleevib8d7ea02018-05-07 20:01:0111424 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711425 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2911426 // Negotiate SPDY to the proxy
11427 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611428 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711429 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2911430
bnc87dcefc2017-05-25 12:47:5811431 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911432 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2911433 TestCompletionCallback callback;
11434 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111435 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911436
11437 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111438 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911439 const HttpResponseInfo* response = trans->GetResponseInfo();
11440
bnc87dcefc2017-05-25 12:47:5811441 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1911442 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5011443 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111444 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911445
11446 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111447 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911448 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
11449
wezca1070932016-05-26 20:30:5211450 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2911451 EXPECT_TRUE(response->headers->IsKeepAlive());
11452
11453 EXPECT_EQ(200, response->headers->response_code());
11454 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11455
11456 std::string response_data;
11457 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111458 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911459 EXPECT_EQ("hello!", response_data);
11460
[email protected]029c83b62013-01-24 05:28:2011461 LoadTimingInfo load_timing_info;
11462 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11463 TestLoadTimingNotReusedWithPac(load_timing_info,
11464 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11465
[email protected]7c6f7ba2012-04-03 04:09:2911466 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5211467 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2911468 EXPECT_EQ(200, push_response->headers->response_code());
11469
11470 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111471 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911472 EXPECT_EQ("pushed", response_data);
11473
[email protected]029c83b62013-01-24 05:28:2011474 LoadTimingInfo push_load_timing_info;
11475 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
11476 TestLoadTimingReusedWithPac(push_load_timing_info);
11477 // The transactions should share a socket ID, despite being for different
11478 // origins.
11479 EXPECT_EQ(load_timing_info.socket_log_id,
11480 push_load_timing_info.socket_log_id);
11481
[email protected]7c6f7ba2012-04-03 04:09:2911482 trans.reset();
11483 push_trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111484 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]7c6f7ba2012-04-03 04:09:2911485}
11486
[email protected]8c843192012-04-05 07:15:0011487// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0111488TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511489 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911490 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511491 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11492 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0011493 HttpRequestInfo request;
11494
11495 request.method = "GET";
bncce36dca22015-04-21 22:11:2311496 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011497 request.traffic_annotation =
11498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0011499
Nicolas Arciniegad2013f92020-02-07 23:00:5611500 session_deps_.proxy_resolution_service =
11501 ConfiguredProxyResolutionService::CreateFixed(
11502 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411503 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711504 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011505
11506 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211507 session_deps_.proxy_resolution_service->SetProxyDelegate(
11508 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011509
danakj1fd259a02016-04-16 03:17:0911510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0011511
Ryan Hamilton0239aac2018-05-19 00:03:1311512 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511513 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0011514
Ryan Hamilton0239aac2018-05-19 00:03:1311515 spdy::SpdySerializedFrame push_rst(
11516 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011517
11518 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111519 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011520 };
11521
Ryan Hamilton0239aac2018-05-19 00:03:1311522 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511523 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011524
Ryan Hamilton0239aac2018-05-19 00:03:1311525 spdy::SpdySerializedFrame stream1_body(
11526 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011527
Ryan Hamilton0239aac2018-05-19 00:03:1311528 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511529 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011530
11531 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111532 CreateMockRead(stream1_reply, 1, ASYNC),
11533 CreateMockRead(stream2_syn, 2, ASYNC),
11534 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911535 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011536 };
11537
Ryan Sleevib8d7ea02018-05-07 20:01:0111538 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711539 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011540 // Negotiate SPDY to the proxy
11541 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611542 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711543 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011544
bnc87dcefc2017-05-25 12:47:5811545 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911546 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011547 TestCompletionCallback callback;
11548 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111549 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011550
11551 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111552 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011553 const HttpResponseInfo* response = trans->GetResponseInfo();
11554
wezca1070932016-05-26 20:30:5211555 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011556 EXPECT_TRUE(response->headers->IsKeepAlive());
11557
11558 EXPECT_EQ(200, response->headers->response_code());
11559 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11560
11561 std::string response_data;
11562 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111563 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011564 EXPECT_EQ("hello!", response_data);
11565
11566 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111567 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]8c843192012-04-05 07:15:0011568}
11569
tbansal8ef1d3e2016-02-03 04:05:4211570// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11571// resources.
bncd16676a2016-07-20 16:23:0111572TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511573 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911574 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511575 proxy_delegate->set_trusted_spdy_proxy(
11576 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11577
tbansal8ef1d3e2016-02-03 04:05:4211578 HttpRequestInfo request;
11579
11580 request.method = "GET";
11581 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011582 request.traffic_annotation =
11583 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211584
11585 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:5611586 session_deps_.proxy_resolution_service =
11587 ConfiguredProxyResolutionService::CreateFixed(
11588 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411589 RecordingBoundTestNetLog log;
tbansal8ef1d3e2016-02-03 04:05:4211590 session_deps_.net_log = log.bound().net_log();
11591
11592 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211593 session_deps_.proxy_resolution_service->SetProxyDelegate(
11594 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211595
danakj1fd259a02016-04-16 03:17:0911596 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211597
Ryan Hamilton0239aac2018-05-19 00:03:1311598 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511599 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311600 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511601 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211602
11603 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111604 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511605 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211606 };
11607
Ryan Hamilton0239aac2018-05-19 00:03:1311608 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511609 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211610
Ryan Hamilton0239aac2018-05-19 00:03:1311611 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311612 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911613
Ryan Hamilton0239aac2018-05-19 00:03:1311614 spdy::SpdySerializedFrame stream1_body(
11615 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211616
Ryan Hamilton0239aac2018-05-19 00:03:1311617 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511618 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211619
Ryan Hamilton0239aac2018-05-19 00:03:1311620 spdy::SpdySerializedFrame stream2_body(
11621 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211622
11623 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111624 CreateMockRead(stream1_reply, 1, ASYNC),
11625 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511626 CreateMockRead(stream1_body, 4, ASYNC),
11627 CreateMockRead(stream2_body, 5, ASYNC),
11628 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211629 };
11630
Ryan Sleevib8d7ea02018-05-07 20:01:0111631 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211632 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11633 // Negotiate SPDY to the proxy
11634 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611635 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211636 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11637
bnc87dcefc2017-05-25 12:47:5811638 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911639 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211640 TestCompletionCallback callback;
11641 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111642 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211643
11644 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111645 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211646 const HttpResponseInfo* response = trans->GetResponseInfo();
11647
wezca1070932016-05-26 20:30:5211648 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211649 EXPECT_TRUE(response->headers->IsKeepAlive());
11650
11651 EXPECT_EQ(200, response->headers->response_code());
11652 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11653
11654 std::string response_data;
11655 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111656 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211657 EXPECT_EQ("hello!", response_data);
11658
11659 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111660 session->CloseAllConnections(ERR_FAILED, "Very good reason");
tbansal8ef1d3e2016-02-03 04:05:4211661}
11662
[email protected]2df19bb2010-08-25 20:13:4611663// Test HTTPS connections to a site with a bad certificate, going through an
11664// HTTPS proxy
bncd16676a2016-07-20 16:23:0111665TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611666 session_deps_.proxy_resolution_service =
11667 ConfiguredProxyResolutionService::CreateFixed(
11668 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611669
11670 HttpRequestInfo request;
11671 request.method = "GET";
bncce36dca22015-04-21 22:11:2311672 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011673 request.traffic_annotation =
11674 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611675
11676 // Attempt to fetch the URL from a server with a bad cert
11677 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711678 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11679 "Host: www.example.org:443\r\n"
11680 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611681 };
11682
11683 MockRead bad_cert_reads[] = {
11684 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611685 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611686 };
11687
11688 // Attempt to fetch the URL with a good cert
11689 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711690 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11691 "Host: www.example.org:443\r\n"
11692 "Proxy-Connection: keep-alive\r\n\r\n"),
11693 MockWrite("GET / HTTP/1.1\r\n"
11694 "Host: www.example.org\r\n"
11695 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611696 };
11697
11698 MockRead good_cert_reads[] = {
11699 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11700 MockRead("HTTP/1.0 200 OK\r\n"),
11701 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11702 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611703 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611704 };
11705
Ryan Sleevib8d7ea02018-05-07 20:01:0111706 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11707 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611708 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11709 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611710
11711 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11713 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11714 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611715
11716 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711717 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11718 session_deps_.socket_factory->AddSocketDataProvider(&data);
11719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611720
[email protected]49639fa2011-12-20 23:22:4111721 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611722
danakj1fd259a02016-04-16 03:17:0911723 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611724 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611725
tfarina42834112016-09-22 13:38:2011726 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611728
11729 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111730 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611731
bnc691fda62016-08-12 00:43:1611732 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111733 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611734
11735 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111736 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611737
bnc691fda62016-08-12 00:43:1611738 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611739
wezca1070932016-05-26 20:30:5211740 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611741 EXPECT_EQ(100, response->headers->GetContentLength());
11742}
11743
bncd16676a2016-07-20 16:23:0111744TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211745 HttpRequestInfo request;
11746 request.method = "GET";
bncce36dca22015-04-21 22:11:2311747 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311748 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11749 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1011750 request.traffic_annotation =
11751 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211752
danakj1fd259a02016-04-16 03:17:0911753 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611754 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711755
[email protected]1c773ea12009-04-28 19:58:4211756 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311757 MockWrite(
11758 "GET / HTTP/1.1\r\n"
11759 "Host: www.example.org\r\n"
11760 "Connection: keep-alive\r\n"
11761 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211762 };
11763
11764 // Lastly, the server responds with the actual content.
11765 MockRead data_reads[] = {
11766 MockRead("HTTP/1.0 200 OK\r\n"),
11767 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11768 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611769 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211770 };
11771
Ryan Sleevib8d7ea02018-05-07 20:01:0111772 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711773 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211774
[email protected]49639fa2011-12-20 23:22:4111775 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211776
tfarina42834112016-09-22 13:38:2011777 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111778 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211779
11780 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111781 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211782}
11783
bncd16676a2016-07-20 16:23:0111784TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011785 // Test user agent values, used both for the request header of the original
11786 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11787 // no request header / no HttpUserAgentSettings object.
11788 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911789
Matt Menked732ea42019-03-08 12:05:0011790 for (const char* setting_user_agent : kTestUserAgents) {
11791 if (!setting_user_agent) {
11792 session_deps_.http_user_agent_settings.reset();
11793 } else {
11794 session_deps_.http_user_agent_settings =
11795 std::make_unique<StaticHttpUserAgentSettings>(
11796 std::string() /* accept-language */, setting_user_agent);
11797 }
11798 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611799 ConfiguredProxyResolutionService::CreateFixed(
11800 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked732ea42019-03-08 12:05:0011801 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11802 for (const char* request_user_agent : kTestUserAgents) {
11803 HttpRequestInfo request;
11804 request.method = "GET";
11805 request.url = GURL("https://www.example.org/");
11806 if (request_user_agent) {
11807 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11808 request_user_agent);
11809 }
11810 request.traffic_annotation =
11811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711812
Matt Menked732ea42019-03-08 12:05:0011813 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911814
Matt Menked732ea42019-03-08 12:05:0011815 std::string expected_request;
11816 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11817 expected_request =
11818 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11819 "Host: www.example.org:443\r\n"
11820 "Proxy-Connection: keep-alive\r\n\r\n";
11821 } else {
11822 expected_request = base::StringPrintf(
11823 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11824 "Host: www.example.org:443\r\n"
11825 "Proxy-Connection: keep-alive\r\n"
11826 "User-Agent: %s\r\n\r\n",
11827 setting_user_agent);
11828 }
11829 MockWrite data_writes[] = {
11830 MockWrite(expected_request.c_str()),
11831 };
11832 MockRead data_reads[] = {
11833 // Return an error, so the transaction stops here (this test isn't
11834 // interested in the rest).
11835 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11836 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11837 MockRead("Proxy-Connection: close\r\n\r\n"),
11838 };
[email protected]da81f132010-08-18 23:39:2911839
Matt Menked732ea42019-03-08 12:05:0011840 StaticSocketDataProvider data(data_reads, data_writes);
11841 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911842
Matt Menked732ea42019-03-08 12:05:0011843 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911844
Matt Menked732ea42019-03-08 12:05:0011845 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11846 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11847
11848 rv = callback.WaitForResult();
11849 EXPECT_THAT(rv, IsOk());
11850 }
11851 }
[email protected]da81f132010-08-18 23:39:2911852}
11853
bncd16676a2016-07-20 16:23:0111854TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211855 HttpRequestInfo request;
11856 request.method = "GET";
bncce36dca22015-04-21 22:11:2311857 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611858 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11859 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011860 request.traffic_annotation =
11861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211862
danakj1fd259a02016-04-16 03:17:0911863 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611864 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711865
[email protected]1c773ea12009-04-28 19:58:4211866 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311867 MockWrite(
11868 "GET / HTTP/1.1\r\n"
11869 "Host: www.example.org\r\n"
11870 "Connection: keep-alive\r\n"
11871 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211872 };
11873
11874 // Lastly, the server responds with the actual content.
11875 MockRead data_reads[] = {
11876 MockRead("HTTP/1.0 200 OK\r\n"),
11877 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11878 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611879 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211880 };
11881
Ryan Sleevib8d7ea02018-05-07 20:01:0111882 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711883 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211884
[email protected]49639fa2011-12-20 23:22:4111885 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211886
tfarina42834112016-09-22 13:38:2011887 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111888 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211889
11890 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111891 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211892}
11893
bncd16676a2016-07-20 16:23:0111894TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211895 HttpRequestInfo request;
11896 request.method = "POST";
bncce36dca22015-04-21 22:11:2311897 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011898 request.traffic_annotation =
11899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211900
danakj1fd259a02016-04-16 03:17:0911901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711903
[email protected]1c773ea12009-04-28 19:58:4211904 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311905 MockWrite(
11906 "POST / HTTP/1.1\r\n"
11907 "Host: www.example.org\r\n"
11908 "Connection: keep-alive\r\n"
11909 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211910 };
11911
11912 // Lastly, the server responds with the actual content.
11913 MockRead data_reads[] = {
11914 MockRead("HTTP/1.0 200 OK\r\n"),
11915 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11916 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611917 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211918 };
11919
Ryan Sleevib8d7ea02018-05-07 20:01:0111920 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711921 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211922
[email protected]49639fa2011-12-20 23:22:4111923 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211924
tfarina42834112016-09-22 13:38:2011925 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111926 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211927
11928 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111929 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211930}
11931
bncd16676a2016-07-20 16:23:0111932TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211933 HttpRequestInfo request;
11934 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311935 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011936 request.traffic_annotation =
11937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211938
danakj1fd259a02016-04-16 03:17:0911939 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611940 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711941
[email protected]1c773ea12009-04-28 19:58:4211942 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311943 MockWrite(
11944 "PUT / HTTP/1.1\r\n"
11945 "Host: www.example.org\r\n"
11946 "Connection: keep-alive\r\n"
11947 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211948 };
11949
11950 // Lastly, the server responds with the actual content.
11951 MockRead data_reads[] = {
11952 MockRead("HTTP/1.0 200 OK\r\n"),
11953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11954 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611955 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211956 };
11957
Ryan Sleevib8d7ea02018-05-07 20:01:0111958 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711959 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211960
[email protected]49639fa2011-12-20 23:22:4111961 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211962
tfarina42834112016-09-22 13:38:2011963 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111964 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211965
11966 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111967 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211968}
11969
bncd16676a2016-07-20 16:23:0111970TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211971 HttpRequestInfo request;
11972 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311973 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011974 request.traffic_annotation =
11975 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211976
danakj1fd259a02016-04-16 03:17:0911977 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611978 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711979
[email protected]1c773ea12009-04-28 19:58:4211980 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311981 MockWrite("HEAD / HTTP/1.1\r\n"
11982 "Host: www.example.org\r\n"
11983 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211984 };
11985
11986 // Lastly, the server responds with the actual content.
11987 MockRead data_reads[] = {
11988 MockRead("HTTP/1.0 200 OK\r\n"),
11989 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11990 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611991 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211992 };
11993
Ryan Sleevib8d7ea02018-05-07 20:01:0111994 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711995 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211996
[email protected]49639fa2011-12-20 23:22:4111997 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211998
tfarina42834112016-09-22 13:38:2011999 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112000 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212001
12002 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112003 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212004}
12005
bncd16676a2016-07-20 16:23:0112006TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4212007 HttpRequestInfo request;
12008 request.method = "GET";
bncce36dca22015-04-21 22:11:2312009 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4212010 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1012011 request.traffic_annotation =
12012 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4212013
danakj1fd259a02016-04-16 03:17:0912014 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612015 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712016
[email protected]1c773ea12009-04-28 19:58:4212017 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312018 MockWrite(
12019 "GET / HTTP/1.1\r\n"
12020 "Host: www.example.org\r\n"
12021 "Connection: keep-alive\r\n"
12022 "Pragma: no-cache\r\n"
12023 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4212024 };
12025
12026 // Lastly, the server responds with the actual content.
12027 MockRead data_reads[] = {
12028 MockRead("HTTP/1.0 200 OK\r\n"),
12029 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12030 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612031 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4212032 };
12033
Ryan Sleevib8d7ea02018-05-07 20:01:0112034 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712035 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4212036
[email protected]49639fa2011-12-20 23:22:4112037 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4212038
tfarina42834112016-09-22 13:38:2012039 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112040 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212041
12042 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112043 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212044}
12045
bncd16676a2016-07-20 16:23:0112046TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4212047 HttpRequestInfo request;
12048 request.method = "GET";
bncce36dca22015-04-21 22:11:2312049 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4212050 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1012051 request.traffic_annotation =
12052 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4212053
danakj1fd259a02016-04-16 03:17:0912054 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612055 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712056
[email protected]1c773ea12009-04-28 19:58:4212057 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312058 MockWrite(
12059 "GET / HTTP/1.1\r\n"
12060 "Host: www.example.org\r\n"
12061 "Connection: keep-alive\r\n"
12062 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4212063 };
12064
12065 // Lastly, the server responds with the actual content.
12066 MockRead data_reads[] = {
12067 MockRead("HTTP/1.0 200 OK\r\n"),
12068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12069 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612070 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4212071 };
12072
Ryan Sleevib8d7ea02018-05-07 20:01:0112073 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712074 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4212075
[email protected]49639fa2011-12-20 23:22:4112076 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4212077
tfarina42834112016-09-22 13:38:2012078 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212080
12081 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112082 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212083}
12084
bncd16676a2016-07-20 16:23:0112085TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4212086 HttpRequestInfo request;
12087 request.method = "GET";
bncce36dca22015-04-21 22:11:2312088 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4312089 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1012090 request.traffic_annotation =
12091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4212092
danakj1fd259a02016-04-16 03:17:0912093 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612094 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712095
[email protected]1c773ea12009-04-28 19:58:4212096 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312097 MockWrite(
12098 "GET / HTTP/1.1\r\n"
12099 "Host: www.example.org\r\n"
12100 "Connection: keep-alive\r\n"
12101 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4212102 };
12103
12104 // Lastly, the server responds with the actual content.
12105 MockRead data_reads[] = {
12106 MockRead("HTTP/1.0 200 OK\r\n"),
12107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12108 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612109 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4212110 };
12111
Ryan Sleevib8d7ea02018-05-07 20:01:0112112 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712113 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4212114
[email protected]49639fa2011-12-20 23:22:4112115 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4212116
tfarina42834112016-09-22 13:38:2012117 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212119
12120 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112121 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212122}
12123
bncd16676a2016-07-20 16:23:0112124TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4712125 HttpRequestInfo request;
12126 request.method = "GET";
bncce36dca22015-04-21 22:11:2312127 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4312128 request.extra_headers.SetHeader("referer", "www.foo.com");
12129 request.extra_headers.SetHeader("hEllo", "Kitty");
12130 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1012131 request.traffic_annotation =
12132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4712133
danakj1fd259a02016-04-16 03:17:0912134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612135 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712136
[email protected]270c6412010-03-29 22:02:4712137 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312138 MockWrite(
12139 "GET / HTTP/1.1\r\n"
12140 "Host: www.example.org\r\n"
12141 "Connection: keep-alive\r\n"
12142 "referer: www.foo.com\r\n"
12143 "hEllo: Kitty\r\n"
12144 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4712145 };
12146
12147 // Lastly, the server responds with the actual content.
12148 MockRead data_reads[] = {
12149 MockRead("HTTP/1.0 200 OK\r\n"),
12150 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12151 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612152 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4712153 };
12154
Ryan Sleevib8d7ea02018-05-07 20:01:0112155 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712156 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4712157
[email protected]49639fa2011-12-20 23:22:4112158 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4712159
tfarina42834112016-09-22 13:38:2012160 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112161 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4712162
12163 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112164 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4712165}
12166
bncd16676a2016-07-20 16:23:0112167TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712168 HttpRequestInfo request;
12169 request.method = "GET";
bncce36dca22015-04-21 22:11:2312170 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012171 request.traffic_annotation =
12172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712173
Lily Houghton8c2f97d2018-01-22 05:06:5912174 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612175 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912176 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412177 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712178 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212179
danakj1fd259a02016-04-16 03:17:0912180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212182
[email protected]3cd17242009-06-23 02:59:0212183 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12184 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12185
12186 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412187 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12188 MockWrite("GET / HTTP/1.1\r\n"
12189 "Host: www.example.org\r\n"
12190 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212191
12192 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412193 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12194 MockRead("HTTP/1.0 200 OK\r\n"),
12195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12196 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212197
Ryan Sleevib8d7ea02018-05-07 20:01:0112198 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712199 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212200
[email protected]49639fa2011-12-20 23:22:4112201 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212202
tfarina42834112016-09-22 13:38:2012203 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212205
12206 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112207 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212208
bnc691fda62016-08-12 00:43:1612209 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212210 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0212211
tbansal2ecbbc72016-10-06 17:15:4712212 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2012213 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612214 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012215 TestLoadTimingNotReusedWithPac(load_timing_info,
12216 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12217
[email protected]3cd17242009-06-23 02:59:0212218 std::string response_text;
bnc691fda62016-08-12 00:43:1612219 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112220 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212221 EXPECT_EQ("Payload", response_text);
12222}
12223
bncd16676a2016-07-20 16:23:0112224TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712225 HttpRequestInfo request;
12226 request.method = "GET";
bncce36dca22015-04-21 22:11:2312227 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012228 request.traffic_annotation =
12229 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712230
Lily Houghton8c2f97d2018-01-22 05:06:5912231 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612232 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912233 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412234 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712235 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212236
danakj1fd259a02016-04-16 03:17:0912237 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612238 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212239
[email protected]3cd17242009-06-23 02:59:0212240 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
12241 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12242
12243 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312244 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2412245 base::size(write_buffer)),
12246 MockWrite("GET / HTTP/1.1\r\n"
12247 "Host: www.example.org\r\n"
12248 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212249
12250 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412251 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
12252 base::size(read_buffer)),
12253 MockRead("HTTP/1.0 200 OK\r\n"),
12254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12255 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512256
Ryan Sleevib8d7ea02018-05-07 20:01:0112257 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712258 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512259
[email protected]8ddf8322012-02-23 18:08:0612260 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3512262
[email protected]49639fa2011-12-20 23:22:4112263 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512264
tfarina42834112016-09-22 13:38:2012265 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512267
12268 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112269 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512270
[email protected]029c83b62013-01-24 05:28:2012271 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612272 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012273 TestLoadTimingNotReusedWithPac(load_timing_info,
12274 CONNECT_TIMING_HAS_SSL_TIMES);
12275
bnc691fda62016-08-12 00:43:1612276 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212277 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712278 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512279
12280 std::string response_text;
bnc691fda62016-08-12 00:43:1612281 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112282 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512283 EXPECT_EQ("Payload", response_text);
12284}
12285
bncd16676a2016-07-20 16:23:0112286TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2012287 HttpRequestInfo request;
12288 request.method = "GET";
bncce36dca22015-04-21 22:11:2312289 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012290 request.traffic_annotation =
12291 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2012292
Nicolas Arciniegad2013f92020-02-07 23:00:5612293 session_deps_.proxy_resolution_service =
12294 ConfiguredProxyResolutionService::CreateFixed(
12295 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412296 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712297 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2012298
danakj1fd259a02016-04-16 03:17:0912299 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612300 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2012301
12302 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12303 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12304
12305 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412306 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12307 MockWrite("GET / HTTP/1.1\r\n"
12308 "Host: www.example.org\r\n"
12309 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2012310
12311 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412312 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12313 MockRead("HTTP/1.0 200 OK\r\n"),
12314 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12315 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2012316
Ryan Sleevib8d7ea02018-05-07 20:01:0112317 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712318 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2012319
12320 TestCompletionCallback callback;
12321
tfarina42834112016-09-22 13:38:2012322 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112323 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2012324
12325 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112326 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012327
bnc691fda62016-08-12 00:43:1612328 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212329 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2012330
12331 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612332 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012333 TestLoadTimingNotReused(load_timing_info,
12334 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12335
12336 std::string response_text;
bnc691fda62016-08-12 00:43:1612337 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112338 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012339 EXPECT_EQ("Payload", response_text);
12340}
12341
bncd16676a2016-07-20 16:23:0112342TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712343 HttpRequestInfo request;
12344 request.method = "GET";
bncce36dca22015-04-21 22:11:2312345 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012346 request.traffic_annotation =
12347 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712348
Lily Houghton8c2f97d2018-01-22 05:06:5912349 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612350 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912351 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412352 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712353 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512354
danakj1fd259a02016-04-16 03:17:0912355 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612356 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512357
[email protected]e0c27be2009-07-15 13:09:3512358 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12359 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712360 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312361 0x05, // Version
12362 0x01, // Command (CONNECT)
12363 0x00, // Reserved.
12364 0x03, // Address type (DOMAINNAME).
12365 0x0F, // Length of domain (15)
12366 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12367 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3712368 };
[email protected]e0c27be2009-07-15 13:09:3512369 const char kSOCKS5OkResponse[] =
12370 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
12371
12372 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412373 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
12374 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
12375 MockWrite("GET / HTTP/1.1\r\n"
12376 "Host: www.example.org\r\n"
12377 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512378
12379 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412380 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12381 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12382 MockRead("HTTP/1.0 200 OK\r\n"),
12383 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12384 MockRead("Payload"),
12385 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512386
Ryan Sleevib8d7ea02018-05-07 20:01:0112387 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712388 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512389
[email protected]49639fa2011-12-20 23:22:4112390 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512391
tfarina42834112016-09-22 13:38:2012392 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512394
12395 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112396 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512397
bnc691fda62016-08-12 00:43:1612398 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212399 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712400 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512401
[email protected]029c83b62013-01-24 05:28:2012402 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612403 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012404 TestLoadTimingNotReusedWithPac(load_timing_info,
12405 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12406
[email protected]e0c27be2009-07-15 13:09:3512407 std::string response_text;
bnc691fda62016-08-12 00:43:1612408 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112409 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512410 EXPECT_EQ("Payload", response_text);
12411}
12412
bncd16676a2016-07-20 16:23:0112413TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712414 HttpRequestInfo request;
12415 request.method = "GET";
bncce36dca22015-04-21 22:11:2312416 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012417 request.traffic_annotation =
12418 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712419
Lily Houghton8c2f97d2018-01-22 05:06:5912420 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612421 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912422 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412423 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712424 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512425
danakj1fd259a02016-04-16 03:17:0912426 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612427 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512428
[email protected]e0c27be2009-07-15 13:09:3512429 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12430 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712431 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312432 0x05, // Version
12433 0x01, // Command (CONNECT)
12434 0x00, // Reserved.
12435 0x03, // Address type (DOMAINNAME).
12436 0x0F, // Length of domain (15)
12437 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12438 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3712439 };
12440
[email protected]e0c27be2009-07-15 13:09:3512441 const char kSOCKS5OkResponse[] =
12442 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
12443
12444 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412445 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2312446 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2412447 base::size(kSOCKS5OkRequest)),
12448 MockWrite("GET / HTTP/1.1\r\n"
12449 "Host: www.example.org\r\n"
12450 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512451
12452 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412453 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12454 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12455 MockRead("HTTP/1.0 200 OK\r\n"),
12456 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12457 MockRead("Payload"),
12458 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212459
Ryan Sleevib8d7ea02018-05-07 20:01:0112460 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712461 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212462
[email protected]8ddf8322012-02-23 18:08:0612463 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0212465
[email protected]49639fa2011-12-20 23:22:4112466 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212467
tfarina42834112016-09-22 13:38:2012468 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212470
12471 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112472 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212473
bnc691fda62016-08-12 00:43:1612474 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212475 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712476 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0212477
[email protected]029c83b62013-01-24 05:28:2012478 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612479 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012480 TestLoadTimingNotReusedWithPac(load_timing_info,
12481 CONNECT_TIMING_HAS_SSL_TIMES);
12482
[email protected]3cd17242009-06-23 02:59:0212483 std::string response_text;
bnc691fda62016-08-12 00:43:1612484 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112485 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212486 EXPECT_EQ("Payload", response_text);
12487}
12488
[email protected]448d4ca52012-03-04 04:12:2312489namespace {
12490
Matt Menkef6edce752019-03-19 17:21:5612491// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0612492
Matt Menkef6edce752019-03-19 17:21:5612493struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0612494 std::string proxy_server;
12495 std::string url;
Matt Menkef6edce752019-03-19 17:21:5612496 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1812497 bool ssl;
[email protected]2d731a32010-04-29 01:04:0612498};
12499
Matt Menkef6edce752019-03-19 17:21:5612500std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0712501 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0912502 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0612503
bnc525e175a2016-06-20 12:36:4012504 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312505 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112506 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1212507 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112508 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4212509 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0712510 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0612511
12512 return session;
12513}
12514
Matt Menkef6edce752019-03-19 17:21:5612515int GroupIdTransactionHelper(const std::string& url,
12516 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0612517 HttpRequestInfo request;
12518 request.method = "GET";
12519 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1012520 request.traffic_annotation =
12521 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612522
bnc691fda62016-08-12 00:43:1612523 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712524
[email protected]49639fa2011-12-20 23:22:4112525 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612526
12527 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012528 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612529}
12530
[email protected]448d4ca52012-03-04 04:12:2312531} // namespace
12532
Matt Menkef6edce752019-03-19 17:21:5612533TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12534 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312535 {
Matt Menkef6edce752019-03-19 17:21:5612536 "", // unused
12537 "http://www.example.org/direct",
12538 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12539 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412540 PrivacyMode::PRIVACY_MODE_DISABLED,
12541 NetworkIsolationKey(),
12542 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612543 false,
bncce36dca22015-04-21 22:11:2312544 },
12545 {
Matt Menkef6edce752019-03-19 17:21:5612546 "", // unused
12547 "http://[2001:1418:13:1::25]/direct",
12548 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12549 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412550 PrivacyMode::PRIVACY_MODE_DISABLED,
12551 NetworkIsolationKey(),
12552 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612553 false,
bncce36dca22015-04-21 22:11:2312554 },
[email protected]04e5be32009-06-26 20:00:3112555
bncce36dca22015-04-21 22:11:2312556 // SSL Tests
12557 {
Matt Menkef6edce752019-03-19 17:21:5612558 "", // unused
12559 "https://www.example.org/direct_ssl",
12560 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12561 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412562 PrivacyMode::PRIVACY_MODE_DISABLED,
12563 NetworkIsolationKey(),
12564 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612565 true,
bncce36dca22015-04-21 22:11:2312566 },
12567 {
Matt Menkef6edce752019-03-19 17:21:5612568 "", // unused
12569 "https://[2001:1418:13:1::25]/direct",
12570 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12571 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412572 PrivacyMode::PRIVACY_MODE_DISABLED,
12573 NetworkIsolationKey(),
12574 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612575 true,
bncce36dca22015-04-21 22:11:2312576 },
12577 {
Matt Menkef6edce752019-03-19 17:21:5612578 "", // unused
12579 "https://host.with.alternate/direct",
12580 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12581 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412582 PrivacyMode::PRIVACY_MODE_DISABLED,
12583 NetworkIsolationKey(),
12584 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612585 true,
bncce36dca22015-04-21 22:11:2312586 },
[email protected]2d731a32010-04-29 01:04:0612587 };
[email protected]2ff8b312010-04-26 22:20:5412588
Avi Drissman4365a4782018-12-28 19:26:2412589 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912590 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612591 ConfiguredProxyResolutionService::CreateFixed(
12592 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912593 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612594 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612595
mmenkee65e7af2015-10-13 17:16:4212596 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612597 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612598 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912599 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012600 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12601 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812602 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612603
12604 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612605 GroupIdTransactionHelper(tests[i].url, session.get()));
12606 EXPECT_EQ(tests[i].expected_group_id,
12607 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312608 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612609 }
[email protected]2d731a32010-04-29 01:04:0612610}
12611
Matt Menkef6edce752019-03-19 17:21:5612612TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12613 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312614 {
Matt Menke4802de62019-03-08 22:47:5012615 "http_proxy",
12616 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612617 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12618 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412619 PrivacyMode::PRIVACY_MODE_DISABLED,
12620 NetworkIsolationKey(),
12621 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012622 false,
bncce36dca22015-04-21 22:11:2312623 },
[email protected]2d731a32010-04-29 01:04:0612624
bncce36dca22015-04-21 22:11:2312625 // SSL Tests
12626 {
Matt Menke4802de62019-03-08 22:47:5012627 "http_proxy",
12628 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612629 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12630 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412631 PrivacyMode::PRIVACY_MODE_DISABLED,
12632 NetworkIsolationKey(),
12633 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012634 true,
bncce36dca22015-04-21 22:11:2312635 },
[email protected]af3490e2010-10-16 21:02:2912636
bncce36dca22015-04-21 22:11:2312637 {
Matt Menke4802de62019-03-08 22:47:5012638 "http_proxy",
12639 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612640 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12641 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412642 PrivacyMode::PRIVACY_MODE_DISABLED,
12643 NetworkIsolationKey(),
12644 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012645 true,
bncce36dca22015-04-21 22:11:2312646 },
[email protected]2d731a32010-04-29 01:04:0612647 };
12648
Avi Drissman4365a4782018-12-28 19:26:2412649 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912650 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612651 ConfiguredProxyResolutionService::CreateFixed(
12652 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912653 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612654 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612655
mmenkee65e7af2015-10-13 17:16:4212656 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612657
Matt Menkee8648fa2019-01-17 16:47:0712658 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12659 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612660 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612661 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912662 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012663 mock_pool_manager->SetSocketPool(proxy_server,
12664 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812665 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612666
12667 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612668 GroupIdTransactionHelper(tests[i].url, session.get()));
12669 EXPECT_EQ(tests[i].expected_group_id,
12670 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612671 }
[email protected]2d731a32010-04-29 01:04:0612672}
12673
Matt Menkef6edce752019-03-19 17:21:5612674TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12675 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312676 {
Matt Menke4802de62019-03-08 22:47:5012677 "socks4://socks_proxy:1080",
12678 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612679 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12680 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412681 PrivacyMode::PRIVACY_MODE_DISABLED,
12682 NetworkIsolationKey(),
12683 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012684 false,
bncce36dca22015-04-21 22:11:2312685 },
12686 {
Matt Menke4802de62019-03-08 22:47:5012687 "socks5://socks_proxy:1080",
12688 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612689 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12690 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412691 PrivacyMode::PRIVACY_MODE_DISABLED,
12692 NetworkIsolationKey(),
12693 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012694 false,
bncce36dca22015-04-21 22:11:2312695 },
[email protected]2d731a32010-04-29 01:04:0612696
bncce36dca22015-04-21 22:11:2312697 // SSL Tests
12698 {
Matt Menke4802de62019-03-08 22:47:5012699 "socks4://socks_proxy:1080",
12700 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612701 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12702 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412703 PrivacyMode::PRIVACY_MODE_DISABLED,
12704 NetworkIsolationKey(),
12705 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012706 true,
bncce36dca22015-04-21 22:11:2312707 },
12708 {
Matt Menke4802de62019-03-08 22:47:5012709 "socks5://socks_proxy:1080",
12710 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612711 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12712 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412713 PrivacyMode::PRIVACY_MODE_DISABLED,
12714 NetworkIsolationKey(),
12715 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012716 true,
bncce36dca22015-04-21 22:11:2312717 },
[email protected]af3490e2010-10-16 21:02:2912718
bncce36dca22015-04-21 22:11:2312719 {
Matt Menke4802de62019-03-08 22:47:5012720 "socks4://socks_proxy:1080",
12721 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612722 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12723 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412724 PrivacyMode::PRIVACY_MODE_DISABLED,
12725 NetworkIsolationKey(),
12726 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012727 true,
bncce36dca22015-04-21 22:11:2312728 },
[email protected]04e5be32009-06-26 20:00:3112729 };
12730
Avi Drissman4365a4782018-12-28 19:26:2412731 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912732 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612733 ConfiguredProxyResolutionService::CreateFixed(
12734 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912735 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612736 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212737
mmenkee65e7af2015-10-13 17:16:4212738 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112739
Matt Menkee8648fa2019-01-17 16:47:0712740 ProxyServer proxy_server(
12741 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12742 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612743 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612744 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912745 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012746 mock_pool_manager->SetSocketPool(proxy_server,
12747 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812748 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112749
bnc691fda62016-08-12 00:43:1612750 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112751
[email protected]2d731a32010-04-29 01:04:0612752 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612753 GroupIdTransactionHelper(tests[i].url, session.get()));
12754 EXPECT_EQ(tests[i].expected_group_id,
12755 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112756 }
12757}
12758
bncd16676a2016-07-20 16:23:0112759TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712760 HttpRequestInfo request;
12761 request.method = "GET";
bncce36dca22015-04-21 22:11:2312762 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012763 request.traffic_annotation =
12764 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712765
Nicolas Arciniegad2013f92020-02-07 23:00:5612766 session_deps_.proxy_resolution_service =
12767 ConfiguredProxyResolutionService::CreateFixed(
12768 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212769
[email protected]69719062010-01-05 20:09:2112770 // This simulates failure resolving all hostnames; that means we will fail
12771 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712772 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212773
danakj1fd259a02016-04-16 03:17:0912774 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612775 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512776
[email protected]49639fa2011-12-20 23:22:4112777 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512778
tfarina42834112016-09-22 13:38:2012779 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112780 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512781
[email protected]9172a982009-06-06 00:30:2512782 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112783 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512784}
12785
[email protected]0877e3d2009-10-17 22:29:5712786// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112787TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712788 HttpRequestInfo request;
12789 request.method = "GET";
12790 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012791 request.traffic_annotation =
12792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712793
12794 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612795 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712796 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112797 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712798 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912799 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712800
[email protected]49639fa2011-12-20 23:22:4112801 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712802
bnc691fda62016-08-12 00:43:1612803 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712804
tfarina42834112016-09-22 13:38:2012805 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712807
12808 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112809 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912810
12811 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612812 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912813 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712814}
12815
zmo9528c9f42015-08-04 22:12:0812816// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112817TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712818 HttpRequestInfo request;
12819 request.method = "GET";
12820 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012821 request.traffic_annotation =
12822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712823
12824 MockRead data_reads[] = {
12825 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612826 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712827 };
12828
Ryan Sleevib8d7ea02018-05-07 20:01:0112829 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712830 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912831 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712832
[email protected]49639fa2011-12-20 23:22:4112833 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712834
bnc691fda62016-08-12 00:43:1612835 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712836
tfarina42834112016-09-22 13:38:2012837 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712839
12840 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112841 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812842
bnc691fda62016-08-12 00:43:1612843 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212844 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812845
wezca1070932016-05-26 20:30:5212846 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812847 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12848
12849 std::string response_data;
bnc691fda62016-08-12 00:43:1612850 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112851 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812852 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912853
12854 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612855 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912856 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712857}
12858
12859// Make sure that a dropped connection while draining the body for auth
12860// restart does the right thing.
bncd16676a2016-07-20 16:23:0112861TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712862 HttpRequestInfo request;
12863 request.method = "GET";
bncce36dca22015-04-21 22:11:2312864 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012865 request.traffic_annotation =
12866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712867
12868 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312869 MockWrite(
12870 "GET / HTTP/1.1\r\n"
12871 "Host: www.example.org\r\n"
12872 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712873 };
12874
12875 MockRead data_reads1[] = {
12876 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12877 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12879 MockRead("Content-Length: 14\r\n\r\n"),
12880 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612881 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712882 };
12883
Ryan Sleevib8d7ea02018-05-07 20:01:0112884 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712885 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712886
bnc691fda62016-08-12 00:43:1612887 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712888 // be issuing -- the final header line contains the credentials.
12889 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312890 MockWrite(
12891 "GET / HTTP/1.1\r\n"
12892 "Host: www.example.org\r\n"
12893 "Connection: keep-alive\r\n"
12894 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712895 };
12896
12897 // Lastly, the server responds with the actual content.
12898 MockRead data_reads2[] = {
12899 MockRead("HTTP/1.1 200 OK\r\n"),
12900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12901 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612902 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712903 };
12904
Ryan Sleevib8d7ea02018-05-07 20:01:0112905 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712906 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912907 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712908
[email protected]49639fa2011-12-20 23:22:4112909 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712910
bnc691fda62016-08-12 00:43:1612911 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012912
tfarina42834112016-09-22 13:38:2012913 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112914 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712915
12916 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112917 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712918
bnc691fda62016-08-12 00:43:1612919 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212920 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812921 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712922
[email protected]49639fa2011-12-20 23:22:4112923 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712924
bnc691fda62016-08-12 00:43:1612925 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112926 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712927
12928 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112929 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712930
bnc691fda62016-08-12 00:43:1612931 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212932 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812933 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712934 EXPECT_EQ(100, response->headers->GetContentLength());
12935}
12936
12937// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112938TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Nicolas Arciniegad2013f92020-02-07 23:00:5612939 session_deps_.proxy_resolution_service =
12940 ConfiguredProxyResolutionService::CreateFixed(
12941 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712942
12943 HttpRequestInfo request;
12944 request.method = "GET";
bncce36dca22015-04-21 22:11:2312945 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012946 request.traffic_annotation =
12947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712948
12949 MockRead proxy_reads[] = {
12950 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612951 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712952 };
12953
Ryan Sleevib8d7ea02018-05-07 20:01:0112954 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612955 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712956
[email protected]bb88e1d32013-05-03 23:11:0712957 session_deps_.socket_factory->AddSocketDataProvider(&data);
12958 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712959
[email protected]49639fa2011-12-20 23:22:4112960 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712961
[email protected]bb88e1d32013-05-03 23:11:0712962 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712963
danakj1fd259a02016-04-16 03:17:0912964 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612965 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712966
tfarina42834112016-09-22 13:38:2012967 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112968 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712969
12970 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112971 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712972}
12973
bncd16676a2016-07-20 16:23:0112974TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612975 HttpRequestInfo request;
12976 request.method = "GET";
bncce36dca22015-04-21 22:11:2312977 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012978 request.traffic_annotation =
12979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612980
danakj1fd259a02016-04-16 03:17:0912981 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612982 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712983
[email protected]e22e1362009-11-23 21:31:1212984 MockRead data_reads[] = {
12985 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612986 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212987 };
[email protected]9492e4a2010-02-24 00:58:4612988
Ryan Sleevib8d7ea02018-05-07 20:01:0112989 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712990 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612991
[email protected]49639fa2011-12-20 23:22:4112992 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612993
tfarina42834112016-09-22 13:38:2012994 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112995 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612996
robpercival214763f2016-07-01 23:27:0112997 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612998
bnc691fda62016-08-12 00:43:1612999 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213000 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4613001
wezca1070932016-05-26 20:30:5213002 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4613003 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
13004
13005 std::string response_data;
bnc691fda62016-08-12 00:43:1613006 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0113007 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1213008}
13009
bncd16676a2016-07-20 16:23:0113010TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1513011 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5213012 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1413013 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2113014 UploadFileElementReader::ScopedOverridingContentLengthForTests
13015 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3313016
danakj1fd259a02016-04-16 03:17:0913017 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1913018 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1413019 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0713020 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2213021 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2713022
13023 HttpRequestInfo request;
13024 request.method = "POST";
bncce36dca22015-04-21 22:11:2313025 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2713026 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1013027 request.traffic_annotation =
13028 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2713029
danakj1fd259a02016-04-16 03:17:0913030 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613031 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3313032
13033 MockRead data_reads[] = {
13034 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
13035 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613036 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3313037 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113038 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713039 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3313040
[email protected]49639fa2011-12-20 23:22:4113041 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3313042
tfarina42834112016-09-22 13:38:2013043 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3313045
13046 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0113047 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3313048
bnc691fda62016-08-12 00:43:1613049 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213050 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3313051
maksim.sisove869bf52016-06-23 17:11:5213052 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3313053
Lei Zhang6dfdc9b12020-06-29 22:15:3113054 base::DeleteFile(temp_file_path);
[email protected]95d88ffe2010-02-04 21:25:3313055}
13056
bncd16676a2016-07-20 16:23:0113057TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1513058 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5213059 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3613060 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4813061 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
13062 base::WriteFile(temp_file, temp_file_content.c_str(),
13063 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1113064 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3613065
danakj1fd259a02016-04-16 03:17:0913066 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1913067 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1413068 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0713069 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2213070 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2713071
13072 HttpRequestInfo request;
13073 request.method = "POST";
bncce36dca22015-04-21 22:11:2313074 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2713075 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1013076 request.traffic_annotation =
13077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2713078
[email protected]999dd8c2013-11-12 06:45:5413079 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0913080 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613081 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3613082
Ryan Sleevib8d7ea02018-05-07 20:01:0113083 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0713084 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3613085
[email protected]49639fa2011-12-20 23:22:4113086 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3613087
tfarina42834112016-09-22 13:38:2013088 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3613090
13091 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0113092 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3613093
Lei Zhang6dfdc9b12020-06-29 22:15:3113094 base::DeleteFile(temp_file);
[email protected]6624b4622010-03-29 19:58:3613095}
13096
bncd16676a2016-07-20 16:23:0113097TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0313098 class FakeUploadElementReader : public UploadElementReader {
13099 public:
Chris Watkins7a41d3552017-12-01 02:13:2713100 FakeUploadElementReader() = default;
13101 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0313102
Matt Menkecc1d3a902018-02-05 18:27:3313103 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0313104
13105 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3313106 int Init(CompletionOnceCallback callback) override {
13107 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0313108 return ERR_IO_PENDING;
13109 }
avibf0746c2015-12-09 19:53:1413110 uint64_t GetContentLength() const override { return 0; }
13111 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2013112 int Read(IOBuffer* buf,
13113 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3313114 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0313115 return ERR_FAILED;
13116 }
13117
13118 private:
Matt Menkecc1d3a902018-02-05 18:27:3313119 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0313120 };
13121
13122 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0913123 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
13124 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2213125 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0313126
13127 HttpRequestInfo request;
13128 request.method = "POST";
bncce36dca22015-04-21 22:11:2313129 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0313130 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1013131 request.traffic_annotation =
13132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0313133
danakj1fd259a02016-04-16 03:17:0913134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813135 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913136 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0313137
13138 StaticSocketDataProvider data;
13139 session_deps_.socket_factory->AddSocketDataProvider(&data);
13140
13141 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2013142 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113143 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5513144 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0313145
13146 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3313147 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
13148 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0313149
13150 // Return Init()'s result after the transaction gets destroyed.
13151 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3313152 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0313153}
13154
[email protected]aeefc9e82010-02-19 16:18:2713155// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0113156TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2713157 HttpRequestInfo request;
13158 request.method = "GET";
bncce36dca22015-04-21 22:11:2313159 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013160 request.traffic_annotation =
13161 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2713162
13163 // First transaction will request a resource and receive a Basic challenge
13164 // with realm="first_realm".
13165 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2313166 MockWrite(
13167 "GET / HTTP/1.1\r\n"
13168 "Host: www.example.org\r\n"
13169 "Connection: keep-alive\r\n"
13170 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713171 };
13172 MockRead data_reads1[] = {
13173 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13174 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13175 "\r\n"),
13176 };
13177
bnc691fda62016-08-12 00:43:1613178 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2713179 // for first_realm. The server will reject and provide a challenge with
13180 // second_realm.
13181 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2313182 MockWrite(
13183 "GET / HTTP/1.1\r\n"
13184 "Host: www.example.org\r\n"
13185 "Connection: keep-alive\r\n"
13186 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
13187 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713188 };
13189 MockRead data_reads2[] = {
13190 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13191 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
13192 "\r\n"),
13193 };
13194
13195 // This again fails, and goes back to first_realm. Make sure that the
13196 // entry is removed from cache.
13197 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2313198 MockWrite(
13199 "GET / HTTP/1.1\r\n"
13200 "Host: www.example.org\r\n"
13201 "Connection: keep-alive\r\n"
13202 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
13203 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713204 };
13205 MockRead data_reads3[] = {
13206 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13207 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13208 "\r\n"),
13209 };
13210
13211 // Try one last time (with the correct password) and get the resource.
13212 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2313213 MockWrite(
13214 "GET / HTTP/1.1\r\n"
13215 "Host: www.example.org\r\n"
13216 "Connection: keep-alive\r\n"
13217 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
13218 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713219 };
13220 MockRead data_reads4[] = {
13221 MockRead("HTTP/1.1 200 OK\r\n"
13222 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5013223 "Content-Length: 5\r\n"
13224 "\r\n"
13225 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2713226 };
13227
Ryan Sleevib8d7ea02018-05-07 20:01:0113228 StaticSocketDataProvider data1(data_reads1, data_writes1);
13229 StaticSocketDataProvider data2(data_reads2, data_writes2);
13230 StaticSocketDataProvider data3(data_reads3, data_writes3);
13231 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0713232 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13233 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13234 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13235 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2713236
[email protected]49639fa2011-12-20 23:22:4113237 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2713238
danakj1fd259a02016-04-16 03:17:0913239 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613240 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5013241
[email protected]aeefc9e82010-02-19 16:18:2713242 // Issue the first request with Authorize headers. There should be a
13243 // password prompt for first_realm waiting to be filled in after the
13244 // transaction completes.
tfarina42834112016-09-22 13:38:2013245 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713247 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0113248 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613249 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213250 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813251 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213252 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413253 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313254 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413255 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913256 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713257
13258 // Issue the second request with an incorrect password. There should be a
13259 // password prompt for second_realm waiting to be filled in after the
13260 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4113261 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1613262 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
13263 callback2.callback());
robpercival214763f2016-07-01 23:27:0113264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713265 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0113266 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613267 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213268 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813269 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213270 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413271 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313272 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413273 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913274 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713275
13276 // Issue the third request with another incorrect password. There should be
13277 // a password prompt for first_realm waiting to be filled in. If the password
13278 // prompt is not present, it indicates that the HttpAuthCacheEntry for
13279 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4113280 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1613281 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
13282 callback3.callback());
robpercival214763f2016-07-01 23:27:0113283 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713284 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0113285 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613286 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213287 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813288 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213289 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413290 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313291 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413292 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913293 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713294
13295 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4113296 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1613297 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
13298 callback4.callback());
robpercival214763f2016-07-01 23:27:0113299 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713300 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0113301 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613302 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213303 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813304 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2713305}
13306
Bence Béky230ac612017-08-30 19:17:0813307// Regression test for https://crbug.com/754395.
13308TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
13309 MockRead data_reads[] = {
13310 MockRead("HTTP/1.1 200 OK\r\n"),
13311 MockRead(kAlternativeServiceHttpHeader),
13312 MockRead("\r\n"),
13313 MockRead("hello world"),
13314 MockRead(SYNCHRONOUS, OK),
13315 };
13316
13317 HttpRequestInfo request;
13318 request.method = "GET";
13319 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013320 request.traffic_annotation =
13321 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0813322
Ryan Sleevib8d7ea02018-05-07 20:01:0113323 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0813324 session_deps_.socket_factory->AddSocketDataProvider(&data);
13325
13326 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913327 ssl.ssl_info.cert =
13328 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13329 ASSERT_TRUE(ssl.ssl_info.cert);
13330 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0813331 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13332
13333 TestCompletionCallback callback;
13334
13335 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13336 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13337
13338 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13340
13341 url::SchemeHostPort test_server(request.url);
13342 HttpServerProperties* http_server_properties =
13343 session->http_server_properties();
13344 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913345 http_server_properties
13346 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13347 .empty());
Bence Béky230ac612017-08-30 19:17:0813348
13349 EXPECT_THAT(callback.WaitForResult(), IsOk());
13350
13351 const HttpResponseInfo* response = trans.GetResponseInfo();
13352 ASSERT_TRUE(response);
13353 ASSERT_TRUE(response->headers);
13354 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13355 EXPECT_FALSE(response->was_fetched_via_spdy);
13356 EXPECT_FALSE(response->was_alpn_negotiated);
13357
13358 std::string response_data;
13359 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13360 EXPECT_EQ("hello world", response_data);
13361
13362 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913363 http_server_properties
13364 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13365 .empty());
Bence Béky230ac612017-08-30 19:17:0813366}
13367
bncd16676a2016-07-20 16:23:0113368TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5213369 MockRead data_reads[] = {
13370 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313371 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213372 MockRead("\r\n"),
13373 MockRead("hello world"),
13374 MockRead(SYNCHRONOUS, OK),
13375 };
13376
13377 HttpRequestInfo request;
13378 request.method = "GET";
bncb26024382016-06-29 02:39:4513379 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013380 request.traffic_annotation =
13381 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213382
Ryan Sleevib8d7ea02018-05-07 20:01:0113383 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213384 session_deps_.socket_factory->AddSocketDataProvider(&data);
13385
bncb26024382016-06-29 02:39:4513386 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913387 ssl.ssl_info.cert =
13388 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13389 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513390 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13391
bncc958faa2015-07-31 18:14:5213392 TestCompletionCallback callback;
13393
danakj1fd259a02016-04-16 03:17:0913394 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213396
tfarina42834112016-09-22 13:38:2013397 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213399
bncb26024382016-06-29 02:39:4513400 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013401 HttpServerProperties* http_server_properties =
13402 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413403 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913404 http_server_properties
13405 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13406 .empty());
bncc958faa2015-07-31 18:14:5213407
robpercival214763f2016-07-01 23:27:0113408 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213409
bnc691fda62016-08-12 00:43:1613410 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213411 ASSERT_TRUE(response);
13412 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213413 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13414 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213415 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213416
13417 std::string response_data;
bnc691fda62016-08-12 00:43:1613418 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213419 EXPECT_EQ("hello world", response_data);
13420
zhongyic4de03032017-05-19 04:07:3413421 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913422 http_server_properties->GetAlternativeServiceInfos(test_server,
13423 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413424 ASSERT_EQ(1u, alternative_service_info_vector.size());
13425 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13426 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413427 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5213428}
13429
Matt Menke3233d8f22019-08-20 21:01:4913430TEST_F(HttpNetworkTransactionTest,
13431 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
13432 base::test::ScopedFeatureList feature_list;
13433 feature_list.InitWithFeatures(
13434 // enabled_features
13435 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
13436 // Need to partition connections by NetworkIsolationKey for
13437 // SpdySessionKeys to include NetworkIsolationKeys.
13438 features::kPartitionConnectionsByNetworkIsolationKey},
13439 // disabled_features
13440 {});
13441 // Since HttpServerProperties caches the feature value, have to create a new
13442 // one.
13443 session_deps_.http_server_properties =
13444 std::make_unique<HttpServerProperties>();
13445
Matt Menke4807a9a2020-11-21 00:14:4113446 const SchemefulSite kSite1(GURL("https://foo.test/"));
13447 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
13448 const SchemefulSite kSite2(GURL("https://bar.test/"));
13449 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
Matt Menke3233d8f22019-08-20 21:01:4913450
13451 MockRead data_reads[] = {
13452 MockRead("HTTP/1.1 200 OK\r\n"),
13453 MockRead(kAlternativeServiceHttpHeader),
13454 MockRead("\r\n"),
13455 MockRead("hello world"),
13456 MockRead(SYNCHRONOUS, OK),
13457 };
13458
13459 HttpRequestInfo request;
13460 request.method = "GET";
13461 request.url = GURL("https://www.example.org/");
13462 request.traffic_annotation =
13463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13464 request.network_isolation_key = kNetworkIsolationKey1;
13465
13466 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
13467 session_deps_.socket_factory->AddSocketDataProvider(&data);
13468
13469 SSLSocketDataProvider ssl(ASYNC, OK);
13470 ssl.ssl_info.cert =
13471 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13472 ASSERT_TRUE(ssl.ssl_info.cert);
13473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13474
13475 TestCompletionCallback callback;
13476
13477 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13478 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13479
13480 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13482
13483 url::SchemeHostPort test_server(request.url);
13484 HttpServerProperties* http_server_properties =
13485 session->http_server_properties();
13486 EXPECT_TRUE(
13487 http_server_properties
13488 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
13489 .empty());
13490
13491 EXPECT_THAT(callback.WaitForResult(), IsOk());
13492
13493 const HttpResponseInfo* response = trans.GetResponseInfo();
13494 ASSERT_TRUE(response);
13495 ASSERT_TRUE(response->headers);
13496 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13497 EXPECT_FALSE(response->was_fetched_via_spdy);
13498 EXPECT_FALSE(response->was_alpn_negotiated);
13499
13500 std::string response_data;
13501 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13502 EXPECT_EQ("hello world", response_data);
13503
13504 AlternativeServiceInfoVector alternative_service_info_vector =
13505 http_server_properties->GetAlternativeServiceInfos(test_server,
13506 kNetworkIsolationKey1);
13507 ASSERT_EQ(1u, alternative_service_info_vector.size());
13508 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13509 EXPECT_EQ(alternative_service,
13510 alternative_service_info_vector[0].alternative_service());
13511
13512 // Make sure the alternative service information is only associated with
13513 // kNetworkIsolationKey1.
13514 EXPECT_TRUE(
13515 http_server_properties
13516 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13517 .empty());
13518 EXPECT_TRUE(
13519 http_server_properties
13520 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13521 .empty());
13522}
13523
bnce3dd56f2016-06-01 10:37:1113524// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113525TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113526 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113527 MockRead data_reads[] = {
13528 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313529 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113530 MockRead("\r\n"),
13531 MockRead("hello world"),
13532 MockRead(SYNCHRONOUS, OK),
13533 };
13534
13535 HttpRequestInfo request;
13536 request.method = "GET";
13537 request.url = GURL("http://www.example.org/");
13538 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013539 request.traffic_annotation =
13540 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113541
Ryan Sleevib8d7ea02018-05-07 20:01:0113542 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113543 session_deps_.socket_factory->AddSocketDataProvider(&data);
13544
13545 TestCompletionCallback callback;
13546
13547 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613548 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113549
13550 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013551 HttpServerProperties* http_server_properties =
13552 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413553 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913554 http_server_properties
13555 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13556 .empty());
bnce3dd56f2016-06-01 10:37:1113557
tfarina42834112016-09-22 13:38:2013558 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113559 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13560 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113561
bnc691fda62016-08-12 00:43:1613562 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113563 ASSERT_TRUE(response);
13564 ASSERT_TRUE(response->headers);
13565 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13566 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213567 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113568
13569 std::string response_data;
bnc691fda62016-08-12 00:43:1613570 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113571 EXPECT_EQ("hello world", response_data);
13572
zhongyic4de03032017-05-19 04:07:3413573 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913574 http_server_properties
13575 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13576 .empty());
bnce3dd56f2016-06-01 10:37:1113577}
13578
bnca86731e2017-04-17 12:31:2813579// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513580// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113581TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513582 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813583 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513584
bnc8bef8da22016-05-30 01:28:2513585 HttpRequestInfo request;
13586 request.method = "GET";
bncb26024382016-06-29 02:39:4513587 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513588 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013589 request.traffic_annotation =
13590 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513591
13592 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13593 StaticSocketDataProvider first_data;
13594 first_data.set_connect_data(mock_connect);
13595 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513596 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613597 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513599
13600 MockRead data_reads[] = {
13601 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13602 MockRead(ASYNC, OK),
13603 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113604 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513605 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13606
13607 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13608
bnc525e175a2016-06-20 12:36:4013609 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513610 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113611 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13612 444);
bnc8bef8da22016-05-30 01:28:2513613 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113614 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713615 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13616 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513617
bnc691fda62016-08-12 00:43:1613618 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513619 TestCompletionCallback callback;
13620
tfarina42834112016-09-22 13:38:2013621 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513622 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113623 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513624}
13625
bnce3dd56f2016-06-01 10:37:1113626// Regression test for https://crbug.com/615497:
13627// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113628TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113629 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113630 HttpRequestInfo request;
13631 request.method = "GET";
13632 request.url = GURL("http://www.example.org/");
13633 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013634 request.traffic_annotation =
13635 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113636
13637 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13638 StaticSocketDataProvider first_data;
13639 first_data.set_connect_data(mock_connect);
13640 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13641
13642 MockRead data_reads[] = {
13643 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13644 MockRead(ASYNC, OK),
13645 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113646 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113647 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13648
13649 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13650
bnc525e175a2016-06-20 12:36:4013651 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113652 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113653 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113654 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113655 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713656 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13657 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113658
bnc691fda62016-08-12 00:43:1613659 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113660 TestCompletionCallback callback;
13661
tfarina42834112016-09-22 13:38:2013662 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113663 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113664 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113665}
13666
bncd16676a2016-07-20 16:23:0113667TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813668 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013670 HttpServerProperties* http_server_properties =
13671 session->http_server_properties();
bncb26024382016-06-29 02:39:4513672 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113673 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813674 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113675 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713676 test_server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813677 session->context().quic_context->params()->supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913678 EXPECT_EQ(1u,
13679 http_server_properties
13680 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13681 .size());
bnc4f575852015-10-14 18:35:0813682
13683 // Send a clear header.
13684 MockRead data_reads[] = {
13685 MockRead("HTTP/1.1 200 OK\r\n"),
13686 MockRead("Alt-Svc: clear\r\n"),
13687 MockRead("\r\n"),
13688 MockRead("hello world"),
13689 MockRead(SYNCHRONOUS, OK),
13690 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113691 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813692 session_deps_.socket_factory->AddSocketDataProvider(&data);
13693
bncb26024382016-06-29 02:39:4513694 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913695 ssl.ssl_info.cert =
13696 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13697 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513698 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13699
bnc4f575852015-10-14 18:35:0813700 HttpRequestInfo request;
13701 request.method = "GET";
bncb26024382016-06-29 02:39:4513702 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013703 request.traffic_annotation =
13704 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813705
13706 TestCompletionCallback callback;
13707
bnc691fda62016-08-12 00:43:1613708 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813709
tfarina42834112016-09-22 13:38:2013710 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113711 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813712
bnc691fda62016-08-12 00:43:1613713 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213714 ASSERT_TRUE(response);
13715 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813716 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13717 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213718 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813719
13720 std::string response_data;
bnc691fda62016-08-12 00:43:1613721 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813722 EXPECT_EQ("hello world", response_data);
13723
zhongyic4de03032017-05-19 04:07:3413724 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913725 http_server_properties
13726 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13727 .empty());
bnc4f575852015-10-14 18:35:0813728}
13729
bncd16676a2016-07-20 16:23:0113730TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213731 MockRead data_reads[] = {
13732 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313733 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13734 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213735 MockRead("hello world"),
13736 MockRead(SYNCHRONOUS, OK),
13737 };
13738
13739 HttpRequestInfo request;
13740 request.method = "GET";
bncb26024382016-06-29 02:39:4513741 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013742 request.traffic_annotation =
13743 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213744
Ryan Sleevib8d7ea02018-05-07 20:01:0113745 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213746 session_deps_.socket_factory->AddSocketDataProvider(&data);
13747
bncb26024382016-06-29 02:39:4513748 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913749 ssl.ssl_info.cert =
13750 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13751 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513752 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13753
bncc958faa2015-07-31 18:14:5213754 TestCompletionCallback callback;
13755
danakj1fd259a02016-04-16 03:17:0913756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613757 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213758
tfarina42834112016-09-22 13:38:2013759 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213761
bncb26024382016-06-29 02:39:4513762 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013763 HttpServerProperties* http_server_properties =
13764 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413765 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913766 http_server_properties
13767 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13768 .empty());
bncc958faa2015-07-31 18:14:5213769
robpercival214763f2016-07-01 23:27:0113770 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213771
bnc691fda62016-08-12 00:43:1613772 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213773 ASSERT_TRUE(response);
13774 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213775 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13776 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213777 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213778
13779 std::string response_data;
bnc691fda62016-08-12 00:43:1613780 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213781 EXPECT_EQ("hello world", response_data);
13782
zhongyic4de03032017-05-19 04:07:3413783 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913784 http_server_properties->GetAlternativeServiceInfos(test_server,
13785 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413786 ASSERT_EQ(2u, alternative_service_info_vector.size());
13787
13788 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13789 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413790 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413791 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13792 1234);
13793 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413794 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213795}
13796
bncd16676a2016-07-20 16:23:0113797TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613798 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213799 HostPortPair alternative("alternative.example.org", 443);
13800 std::string origin_url = "https://origin.example.org:443";
13801 std::string alternative_url = "https://alternative.example.org:443";
13802
13803 // Negotiate HTTP/1.1 with alternative.example.org.
13804 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613805 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213806 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13807
13808 // HTTP/1.1 data for request.
13809 MockWrite http_writes[] = {
13810 MockWrite("GET / HTTP/1.1\r\n"
13811 "Host: alternative.example.org\r\n"
13812 "Connection: keep-alive\r\n\r\n"),
13813 };
13814
13815 MockRead http_reads[] = {
13816 MockRead("HTTP/1.1 200 OK\r\n"
13817 "Content-Type: text/html; charset=iso-8859-1\r\n"
13818 "Content-Length: 40\r\n\r\n"
13819 "first HTTP/1.1 response from alternative"),
13820 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113821 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213822 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13823
13824 StaticSocketDataProvider data_refused;
13825 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13826 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13827
zhongyi3d4a55e72016-04-22 20:36:4613828 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913829 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013830 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213831 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113832 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213833 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113834 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713835 server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813836 DefaultSupportedQuicVersions());
zhongyi48704c182015-12-07 07:52:0213837 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513838 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13839 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213840
zhongyi48704c182015-12-07 07:52:0213841 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613842 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213843 request.method = "GET";
13844 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013845 request.traffic_annotation =
13846 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13847
zhongyi48704c182015-12-07 07:52:0213848 TestCompletionCallback callback;
13849 NetErrorDetails details;
13850 EXPECT_FALSE(details.quic_broken);
13851
tfarina42834112016-09-22 13:38:2013852 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613853 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213854 EXPECT_TRUE(details.quic_broken);
13855}
13856
bncd16676a2016-07-20 16:23:0113857TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613858 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213859 HostPortPair alternative1("alternative1.example.org", 443);
13860 HostPortPair alternative2("alternative2.example.org", 443);
13861 std::string origin_url = "https://origin.example.org:443";
13862 std::string alternative_url1 = "https://alternative1.example.org:443";
13863 std::string alternative_url2 = "https://alternative2.example.org:443";
13864
13865 // Negotiate HTTP/1.1 with alternative1.example.org.
13866 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613867 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213868 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13869
13870 // HTTP/1.1 data for request.
13871 MockWrite http_writes[] = {
13872 MockWrite("GET / HTTP/1.1\r\n"
13873 "Host: alternative1.example.org\r\n"
13874 "Connection: keep-alive\r\n\r\n"),
13875 };
13876
13877 MockRead http_reads[] = {
13878 MockRead("HTTP/1.1 200 OK\r\n"
13879 "Content-Type: text/html; charset=iso-8859-1\r\n"
13880 "Content-Length: 40\r\n\r\n"
13881 "first HTTP/1.1 response from alternative1"),
13882 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113883 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213884 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13885
13886 StaticSocketDataProvider data_refused;
13887 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13888 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13889
danakj1fd259a02016-04-16 03:17:0913890 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013891 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213892 session->http_server_properties();
13893
zhongyi3d4a55e72016-04-22 20:36:4613894 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213895 AlternativeServiceInfoVector alternative_service_info_vector;
13896 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13897
bnc3472afd2016-11-17 15:27:2113898 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113899 alternative_service_info_vector.push_back(
13900 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13901 alternative_service1, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813902 session->context().quic_context->params()->supported_versions));
bnc3472afd2016-11-17 15:27:2113903 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113904 alternative_service_info_vector.push_back(
13905 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13906 alternative_service2, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813907 session->context().quic_context->params()->supported_versions));
zhongyi48704c182015-12-07 07:52:0213908
13909 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913910 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213911
13912 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513913 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13914 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913915 EXPECT_EQ(2u, http_server_properties
13916 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13917 .size());
zhongyi48704c182015-12-07 07:52:0213918
zhongyi48704c182015-12-07 07:52:0213919 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613920 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213921 request.method = "GET";
13922 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013923 request.traffic_annotation =
13924 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13925
zhongyi48704c182015-12-07 07:52:0213926 TestCompletionCallback callback;
13927 NetErrorDetails details;
13928 EXPECT_FALSE(details.quic_broken);
13929
tfarina42834112016-09-22 13:38:2013930 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613931 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213932 EXPECT_FALSE(details.quic_broken);
13933}
13934
bncd16676a2016-07-20 16:23:0113935TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213936 HttpRequestInfo request;
13937 request.method = "GET";
bncb26024382016-06-29 02:39:4513938 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013939 request.traffic_annotation =
13940 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213941
[email protected]d973e99a2012-02-17 21:02:3613942 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213943 StaticSocketDataProvider first_data;
13944 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713945 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513946 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613947 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213949
13950 MockRead data_reads[] = {
13951 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13952 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613953 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213954 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113955 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713956 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213957
danakj1fd259a02016-04-16 03:17:0913958 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213959
bnc525e175a2016-06-20 12:36:4013960 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313961 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613962 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113963 // Port must be < 1024, or the header will be ignored (since initial port was
13964 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113965 // Port is ignored by MockConnect anyway.
13966 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13967 666);
bnc7dc7e1b42015-07-28 14:43:1213968 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113969 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713970 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213971
bnc691fda62016-08-12 00:43:1613972 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113973 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213974
tfarina42834112016-09-22 13:38:2013975 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113976 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13977 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213978
bnc691fda62016-08-12 00:43:1613979 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213980 ASSERT_TRUE(response);
13981 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213982 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13983
13984 std::string response_data;
bnc691fda62016-08-12 00:43:1613985 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213986 EXPECT_EQ("hello world", response_data);
13987
zhongyic4de03032017-05-19 04:07:3413988 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913989 http_server_properties->GetAlternativeServiceInfos(server,
13990 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413991 ASSERT_EQ(1u, alternative_service_info_vector.size());
13992 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413993 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513994 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13995 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213996}
13997
bnc55ff9da2015-08-19 18:42:3513998// Ensure that we are not allowed to redirect traffic via an alternate protocol
13999// to an unrestricted (port >= 1024) when the original traffic was on a
14000// restricted port (port < 1024). Ensure that we can redirect in all other
14001// cases.
bncd16676a2016-07-20 16:23:0114002TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1114003 HttpRequestInfo restricted_port_request;
14004 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514005 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1114006 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014007 restricted_port_request.traffic_annotation =
14008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114009
[email protected]d973e99a2012-02-17 21:02:3614010 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114011 StaticSocketDataProvider first_data;
14012 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714013 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114014
14015 MockRead data_reads[] = {
14016 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14017 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614018 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114019 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114020 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714021 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4514022 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614023 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514024 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1114025
danakj1fd259a02016-04-16 03:17:0914026 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114027
bnc525e175a2016-06-20 12:36:4014028 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314029 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114030 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2114031 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14032 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214033 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114034 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714035 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
14036 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114037
bnc691fda62016-08-12 00:43:1614038 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114039 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114040
tfarina42834112016-09-22 13:38:2014041 int rv = trans.Start(&restricted_port_request, callback.callback(),
14042 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114044 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0114045 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1914046}
[email protected]3912662a32011-10-04 00:51:1114047
bnc55ff9da2015-08-19 18:42:3514048// Ensure that we are allowed to redirect traffic via an alternate protocol to
14049// an unrestricted (port >= 1024) when the original traffic was on a restricted
14050// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0114051TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0714052 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1914053
14054 HttpRequestInfo restricted_port_request;
14055 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514056 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1914057 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014058 restricted_port_request.traffic_annotation =
14059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1914060
14061 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
14062 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]c54c6962013-02-01 04:53:1914065
14066 MockRead data_reads[] = {
14067 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14068 MockRead("hello world"),
14069 MockRead(ASYNC, OK),
14070 };
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]c54c6962013-02-01 04:53:1914076
danakj1fd259a02016-04-16 03:17:0914077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1914078
bnc525e175a2016-06-20 12:36:4014079 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1914080 session->http_server_properties();
14081 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2114082 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14083 kUnrestrictedAlternatePort);
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(restricted_port_request.url), NetworkIsolationKey(),
14087 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1914088
bnc691fda62016-08-12 00:43:1614089 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1914090 TestCompletionCallback callback;
14091
tfarina42834112016-09-22 13:38:2014092 EXPECT_EQ(ERR_IO_PENDING,
14093 trans.Start(&restricted_port_request, callback.callback(),
14094 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1914095 // Change to unrestricted port should succeed.
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, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1114104 HttpRequestInfo restricted_port_request;
14105 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514106 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1114107 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014108 restricted_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();
[email protected]3912662a32011-10-04 00:51:1114131 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114132 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14133 kRestrictedAlternatePort);
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(restricted_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
tfarina42834112016-09-22 13:38:2014142 int rv = trans.Start(&restricted_port_request, callback.callback(),
14143 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 restricted 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
14150// to an unrestricted (port >= 1024) when the original traffic was on a
14151// restricted port (port < 1024). Ensure that we can redirect in all other
14152// cases.
bncd16676a2016-07-20 16:23:0114153TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1114154 HttpRequestInfo unrestricted_port_request;
14155 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514156 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114157 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014158 unrestricted_port_request.traffic_annotation =
14159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114160
[email protected]d973e99a2012-02-17 21:02:3614161 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114162 StaticSocketDataProvider first_data;
14163 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714164 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114165
14166 MockRead data_reads[] = {
14167 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14168 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614169 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114170 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114171 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714172 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4514173 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614174 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514175 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1114176
danakj1fd259a02016-04-16 03:17:0914177 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114178
bnc525e175a2016-06-20 12:36:4014179 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314180 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114181 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114182 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14183 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214184 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114185 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714186 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14187 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114188
bnc691fda62016-08-12 00:43:1614189 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114190 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114191
bnc691fda62016-08-12 00:43:1614192 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014193 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114195 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0114196 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114197}
14198
bnc55ff9da2015-08-19 18:42:3514199// Ensure that we are not allowed to redirect traffic via an alternate protocol
14200// to an unrestricted (port >= 1024) when the original traffic was on a
14201// restricted port (port < 1024). Ensure that we can redirect in all other
14202// cases.
bncd16676a2016-07-20 16:23:0114203TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1114204 HttpRequestInfo unrestricted_port_request;
14205 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514206 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114207 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014208 unrestricted_port_request.traffic_annotation =
14209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114210
[email protected]d973e99a2012-02-17 21:02:3614211 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114212 StaticSocketDataProvider first_data;
14213 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714214 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114215
14216 MockRead data_reads[] = {
14217 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14218 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614219 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114220 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114221 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714222 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1114223
bncb26024382016-06-29 02:39:4514224 SSLSocketDataProvider ssl(ASYNC, OK);
14225 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14226
danakj1fd259a02016-04-16 03:17:0914227 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114228
bnc525e175a2016-06-20 12:36:4014229 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314230 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2214231 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2114232 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14233 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214234 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114235 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714236 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14237 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114238
bnc691fda62016-08-12 00:43:1614239 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114240 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114241
bnc691fda62016-08-12 00:43:1614242 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014243 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114244 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114245 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0114246 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114247}
14248
bnc55ff9da2015-08-19 18:42:3514249// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2114250// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
14251// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0114252TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0214253 HttpRequestInfo request;
14254 request.method = "GET";
bncce36dca22015-04-21 22:11:2314255 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014256 request.traffic_annotation =
14257 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0214258
14259 // The alternate protocol request will error out before we attempt to connect,
14260 // so only the standard HTTP request will try to connect.
14261 MockRead data_reads[] = {
14262 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14263 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614264 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0214265 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114266 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714267 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0214268
danakj1fd259a02016-04-16 03:17:0914269 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0214270
bnc525e175a2016-06-20 12:36:4014271 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0214272 session->http_server_properties();
14273 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2114274 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14275 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1214276 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114277 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714278 url::SchemeHostPort(request.url), NetworkIsolationKey(),
14279 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0214280
bnc691fda62016-08-12 00:43:1614281 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0214282 TestCompletionCallback callback;
14283
tfarina42834112016-09-22 13:38:2014284 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114285 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0214286 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0114287 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214288
bnc691fda62016-08-12 00:43:1614289 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214290 ASSERT_TRUE(response);
14291 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0214292 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14293
14294 std::string response_data;
bnc691fda62016-08-12 00:43:1614295 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214296 EXPECT_EQ("hello world", response_data);
14297}
14298
bncd16676a2016-07-20 16:23:0114299TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5414300 HttpRequestInfo request;
14301 request.method = "GET";
bncb26024382016-06-29 02:39:4514302 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014303 request.traffic_annotation =
14304 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414305
14306 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214307 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314308 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214309 MockRead("\r\n"),
14310 MockRead("hello world"),
14311 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14312 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5414313
Ryan Sleevib8d7ea02018-05-07 20:01:0114314 StaticSocketDataProvider first_transaction(data_reads,
14315 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714316 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514317 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614318 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414320
bnc032658ba2016-09-26 18:17:1514321 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414322
Ryan Hamilton0239aac2018-05-19 00:03:1314323 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514324 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114325 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414326
Raul Tambre94493c652019-03-11 17:18:3514327 spdy::SpdySerializedFrame resp(
14328 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314329 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414330 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114331 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414332 };
14333
Ryan Sleevib8d7ea02018-05-07 20:01:0114334 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714335 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414336
[email protected]d973e99a2012-02-17 21:02:3614337 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114338 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514339 hanging_non_alternate_protocol_socket.set_connect_data(
14340 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714341 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514342 &hanging_non_alternate_protocol_socket);
14343
[email protected]49639fa2011-12-20 23:22:4114344 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414345
danakj1fd259a02016-04-16 03:17:0914346 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814347 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914348 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414349
tfarina42834112016-09-22 13:38:2014350 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114351 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14352 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414353
14354 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214355 ASSERT_TRUE(response);
14356 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414357 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14358
14359 std::string response_data;
robpercival214763f2016-07-01 23:27:0114360 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414361 EXPECT_EQ("hello world", response_data);
14362
bnc87dcefc2017-05-25 12:47:5814363 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914364 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414365
tfarina42834112016-09-22 13:38:2014366 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14368 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414369
14370 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214371 ASSERT_TRUE(response);
14372 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214373 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314374 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214375 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414376
robpercival214763f2016-07-01 23:27:0114377 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414378 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5414379}
14380
bncd16676a2016-07-20 16:23:0114381TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5514382 HttpRequestInfo request;
14383 request.method = "GET";
bncb26024382016-06-29 02:39:4514384 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014385 request.traffic_annotation =
14386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514387
bncb26024382016-06-29 02:39:4514388 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5514389 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214390 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314391 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214392 MockRead("\r\n"),
14393 MockRead("hello world"),
14394 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14395 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514396 };
14397
Ryan Sleevib8d7ea02018-05-07 20:01:0114398 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4514399 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5514400
bncb26024382016-06-29 02:39:4514401 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914402 ssl_http11.ssl_info.cert =
14403 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14404 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4514405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
14406
14407 // Second transaction starts an alternative and a non-alternative Job.
14408 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3614409 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114410 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1814411 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1814412 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
14413
Ryan Sleevib8d7ea02018-05-07 20:01:0114414 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1814415 hanging_socket2.set_connect_data(never_finishing_connect);
14416 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5514417
bncb26024382016-06-29 02:39:4514418 // Third transaction starts an alternative and a non-alternative job.
14419 // The non-alternative job hangs, but the alternative one succeeds.
14420 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1314421 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4514422 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1314423 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4514424 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5514425 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4114426 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5514427 };
Raul Tambre94493c652019-03-11 17:18:3514428 spdy::SpdySerializedFrame resp1(
14429 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314430 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3514431 spdy::SpdySerializedFrame resp2(
14432 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1314433 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5514434 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114435 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
14436 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1314437 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5514438 };
14439
Ryan Sleevib8d7ea02018-05-07 20:01:0114440 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714441 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5514442
bnc032658ba2016-09-26 18:17:1514443 AddSSLSocketData();
bncb26024382016-06-29 02:39:4514444
Ryan Sleevib8d7ea02018-05-07 20:01:0114445 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1814446 hanging_socket3.set_connect_data(never_finishing_connect);
14447 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5514448
danakj1fd259a02016-04-16 03:17:0914449 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4114450 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5014451 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514452
tfarina42834112016-09-22 13:38:2014453 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114454 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14455 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514456
14457 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5214458 ASSERT_TRUE(response);
14459 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514460 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14461
14462 std::string response_data;
robpercival214763f2016-07-01 23:27:0114463 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514464 EXPECT_EQ("hello world", response_data);
14465
[email protected]49639fa2011-12-20 23:22:4114466 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5014467 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014468 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514470
[email protected]49639fa2011-12-20 23:22:4114471 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5014472 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014473 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114474 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514475
robpercival214763f2016-07-01 23:27:0114476 EXPECT_THAT(callback2.WaitForResult(), IsOk());
14477 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514478
14479 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5214480 ASSERT_TRUE(response);
14481 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214482 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514483 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214484 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114485 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514486 EXPECT_EQ("hello!", response_data);
14487
14488 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5214489 ASSERT_TRUE(response);
14490 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214491 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514492 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214493 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114494 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514495 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5514496}
14497
bncd16676a2016-07-20 16:23:0114498TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5314499 session_deps_.host_resolver->set_synchronous_mode(true);
14500
[email protected]2d6728692011-03-12 01:39:5514501 HttpRequestInfo request;
14502 request.method = "GET";
bncb26024382016-06-29 02:39:4514503 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014504 request.traffic_annotation =
14505 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514506
14507 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214508 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314509 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214510 MockRead("\r\n"),
14511 MockRead("hello world"),
14512 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14513 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514514 };
14515
Ryan Sleevib8d7ea02018-05-07 20:01:0114516 StaticSocketDataProvider first_transaction(data_reads,
14517 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714518 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5514519
[email protected]8ddf8322012-02-23 18:08:0614520 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914521 ssl.ssl_info.cert =
14522 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14523 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514525
[email protected]d973e99a2012-02-17 21:02:3614526 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114527 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514528 hanging_alternate_protocol_socket.set_connect_data(
14529 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714530 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514531 &hanging_alternate_protocol_socket);
14532
bncb26024382016-06-29 02:39:4514533 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114534 StaticSocketDataProvider second_transaction(data_reads,
14535 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814536 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514537 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514538
[email protected]49639fa2011-12-20 23:22:4114539 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514540
danakj1fd259a02016-04-16 03:17:0914541 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814542 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914543 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514544
tfarina42834112016-09-22 13:38:2014545 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14547 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514548
14549 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214550 ASSERT_TRUE(response);
14551 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514552 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14553
14554 std::string response_data;
robpercival214763f2016-07-01 23:27:0114555 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514556 EXPECT_EQ("hello world", response_data);
14557
bnc87dcefc2017-05-25 12:47:5814558 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914559 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514560
tfarina42834112016-09-22 13:38:2014561 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14563 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514564
14565 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214566 ASSERT_TRUE(response);
14567 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514568 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14569 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214570 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514571
robpercival214763f2016-07-01 23:27:0114572 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514573 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514574}
14575
bnc2e884782016-08-11 19:45:1914576// Test that proxy is resolved using the origin url,
14577// regardless of the alternative server.
14578TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14579 // Configure proxy to bypass www.example.org, which is the origin URL.
14580 ProxyConfig proxy_config;
14581 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14582 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914583 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14584 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914585
14586 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914587 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914588 &capturing_proxy_resolver);
14589
Matt Muellerd9342e3a2019-11-26 01:41:1414590 RecordingTestNetLog net_log;
bnc2e884782016-08-11 19:45:1914591
Bence Béky53a5aef2018-03-29 21:54:1214592 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614593 std::make_unique<ConfiguredProxyResolutionService>(
Bence Béky53a5aef2018-03-29 21:54:1214594 std::move(proxy_config_service), std::move(proxy_resolver_factory),
Eric Roman3be01ba2020-04-03 21:37:0914595 &net_log, /*quick_check_enabled=*/true);
bnc2e884782016-08-11 19:45:1914596
14597 session_deps_.net_log = &net_log;
14598
14599 // Configure alternative service with a hostname that is not bypassed by the
14600 // proxy.
14601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14602 HttpServerProperties* http_server_properties =
14603 session->http_server_properties();
14604 url::SchemeHostPort server("https", "www.example.org", 443);
14605 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114606 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914607 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114608 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714609 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914610
14611 // Non-alternative job should hang.
14612 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114613 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914614 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14615 session_deps_.socket_factory->AddSocketDataProvider(
14616 &hanging_alternate_protocol_socket);
14617
bnc032658ba2016-09-26 18:17:1514618 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914619
14620 HttpRequestInfo request;
14621 request.method = "GET";
14622 request.url = GURL("https://www.example.org/");
14623 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014624 request.traffic_annotation =
14625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914626
Ryan Hamilton0239aac2018-05-19 00:03:1314627 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914628 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14629
14630 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14631
Ryan Hamilton0239aac2018-05-19 00:03:1314632 spdy::SpdySerializedFrame resp(
14633 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14634 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914635 MockRead spdy_reads[] = {
14636 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14637 };
14638
Ryan Sleevib8d7ea02018-05-07 20:01:0114639 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914640 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14641
14642 TestCompletionCallback callback;
14643
14644 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14645
tfarina42834112016-09-22 13:38:2014646 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914647 EXPECT_THAT(callback.GetResult(rv), IsOk());
14648
14649 const HttpResponseInfo* response = trans.GetResponseInfo();
14650 ASSERT_TRUE(response);
14651 ASSERT_TRUE(response->headers);
14652 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14653 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214654 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914655
14656 std::string response_data;
14657 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14658 EXPECT_EQ("hello!", response_data);
14659
14660 // Origin host bypasses proxy, no resolution should have happened.
Matt Menke8045afd2019-11-14 20:31:1914661 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
bnc2e884782016-08-11 19:45:1914662}
14663
bncd16676a2016-07-20 16:23:0114664TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114665 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214666 proxy_config.set_auto_detect(true);
14667 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114668
sammc5dd160c2015-04-02 02:43:1314669 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914670 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614671 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4914672 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14673 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14674 std::make_unique<CapturingProxyResolverFactory>(
14675 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:0914676 nullptr, /*quick_check_enabled=*/true);
Matt Muellerd9342e3a2019-11-26 01:41:1414677 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714678 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114679
14680 HttpRequestInfo request;
14681 request.method = "GET";
bncb26024382016-06-29 02:39:4514682 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014683 request.traffic_annotation =
14684 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114685
14686 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214687 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314688 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214689 MockRead("\r\n"),
14690 MockRead("hello world"),
14691 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14692 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114693 };
14694
Ryan Sleevib8d7ea02018-05-07 20:01:0114695 StaticSocketDataProvider first_transaction(data_reads,
14696 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714697 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514698 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614699 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114701
bnc032658ba2016-09-26 18:17:1514702 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114703
Ryan Hamilton0239aac2018-05-19 00:03:1314704 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514705 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114706 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314707 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514708 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14709 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314710 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114711 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114712 };
14713
[email protected]d911f1b2010-05-05 22:39:4214714 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14715
Raul Tambre94493c652019-03-11 17:18:3514716 spdy::SpdySerializedFrame resp(
14717 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314718 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114719 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114720 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14721 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114722 };
14723
Ryan Sleevib8d7ea02018-05-07 20:01:0114724 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714725 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114726
[email protected]d973e99a2012-02-17 21:02:3614727 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114728 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514729 hanging_non_alternate_protocol_socket.set_connect_data(
14730 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714731 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514732 &hanging_non_alternate_protocol_socket);
14733
[email protected]49639fa2011-12-20 23:22:4114734 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114735
danakj1fd259a02016-04-16 03:17:0914736 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814737 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914738 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114739
tfarina42834112016-09-22 13:38:2014740 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114741 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14742 EXPECT_THAT(callback.WaitForResult(), IsOk());
14743
14744 const HttpResponseInfo* response = trans->GetResponseInfo();
14745 ASSERT_TRUE(response);
14746 ASSERT_TRUE(response->headers);
14747 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14748 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214749 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114750
14751 std::string response_data;
14752 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14753 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114754
bnc87dcefc2017-05-25 12:47:5814755 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914756 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114757
tfarina42834112016-09-22 13:38:2014758 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114759 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14760 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114761
mmenkea2dcd3bf2016-08-16 21:49:4114762 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214763 ASSERT_TRUE(response);
14764 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214765 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314766 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214767 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114768
robpercival214763f2016-07-01 23:27:0114769 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114770 EXPECT_EQ("hello!", response_data);
Matt Menke8045afd2019-11-14 20:31:1914771 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
bncb26024382016-06-29 02:39:4514772 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914773 capturing_proxy_resolver.lookup_info()[0].url.spec());
bncce36dca22015-04-21 22:11:2314774 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914775 capturing_proxy_resolver.lookup_info()[1].url.spec());
[email protected]631f1322010-04-30 17:59:1114776
[email protected]029c83b62013-01-24 05:28:2014777 LoadTimingInfo load_timing_info;
14778 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14779 TestLoadTimingNotReusedWithPac(load_timing_info,
14780 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114781}
[email protected]631f1322010-04-30 17:59:1114782
bncd16676a2016-07-20 16:23:0114783TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814784 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414785 HttpRequestInfo request;
14786 request.method = "GET";
bncb26024382016-06-29 02:39:4514787 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014788 request.traffic_annotation =
14789 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414790
14791 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214792 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314793 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214794 MockRead("\r\n"),
14795 MockRead("hello world"),
14796 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414797 };
14798
Ryan Sleevib8d7ea02018-05-07 20:01:0114799 StaticSocketDataProvider first_transaction(data_reads,
14800 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714801 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514802 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614803 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514804 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414805
bnc032658ba2016-09-26 18:17:1514806 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414807
Ryan Hamilton0239aac2018-05-19 00:03:1314808 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514809 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114810 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414811
Raul Tambre94493c652019-03-11 17:18:3514812 spdy::SpdySerializedFrame resp(
14813 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314814 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414815 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114816 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414817 };
14818
Ryan Sleevib8d7ea02018-05-07 20:01:0114819 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714820 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414821
[email protected]83039bb2011-12-09 18:43:5514822 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414823
danakj1fd259a02016-04-16 03:17:0914824 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414825
bnc87dcefc2017-05-25 12:47:5814826 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914827 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414828
tfarina42834112016-09-22 13:38:2014829 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114830 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14831 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414832
14833 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214834 ASSERT_TRUE(response);
14835 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414836 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14837
14838 std::string response_data;
robpercival214763f2016-07-01 23:27:0114839 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414840 EXPECT_EQ("hello world", response_data);
14841
14842 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514843 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014844 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114845 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414846 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14847 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714848 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214849 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814850
bnc87dcefc2017-05-25 12:47:5814851 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914852 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414853
tfarina42834112016-09-22 13:38:2014854 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114855 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14856 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414857
14858 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214859 ASSERT_TRUE(response);
14860 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214861 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314862 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214863 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414864
robpercival214763f2016-07-01 23:27:0114865 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414866 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214867}
14868
[email protected]044de0642010-06-17 10:42:1514869// GenerateAuthToken is a mighty big test.
14870// It tests all permutation of GenerateAuthToken behavior:
14871// - Synchronous and Asynchronous completion.
14872// - OK or error on completion.
14873// - Direct connection, non-authenticating proxy, and authenticating proxy.
14874// - HTTP or HTTPS backend (to include proxy tunneling).
14875// - Non-authenticating and authenticating backend.
14876//
[email protected]fe3b7dc2012-02-03 19:52:0914877// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514878// problems generating an auth token for an authenticating proxy, we don't
14879// need to test all permutations of the backend server).
14880//
14881// The test proceeds by going over each of the configuration cases, and
14882// potentially running up to three rounds in each of the tests. The TestConfig
14883// specifies both the configuration for the test as well as the expectations
14884// for the results.
bncd16676a2016-07-20 16:23:0114885TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014886 static const char kServer[] = "http://www.example.com";
14887 static const char kSecureServer[] = "https://www.example.com";
14888 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514889
14890 enum AuthTiming {
14891 AUTH_NONE,
14892 AUTH_SYNC,
14893 AUTH_ASYNC,
14894 };
14895
14896 const MockWrite kGet(
14897 "GET / HTTP/1.1\r\n"
14898 "Host: www.example.com\r\n"
14899 "Connection: keep-alive\r\n\r\n");
14900 const MockWrite kGetProxy(
14901 "GET http://www.example.com/ HTTP/1.1\r\n"
14902 "Host: www.example.com\r\n"
14903 "Proxy-Connection: keep-alive\r\n\r\n");
14904 const MockWrite kGetAuth(
14905 "GET / HTTP/1.1\r\n"
14906 "Host: www.example.com\r\n"
14907 "Connection: keep-alive\r\n"
14908 "Authorization: auth_token\r\n\r\n");
14909 const MockWrite kGetProxyAuth(
14910 "GET http://www.example.com/ HTTP/1.1\r\n"
14911 "Host: www.example.com\r\n"
14912 "Proxy-Connection: keep-alive\r\n"
14913 "Proxy-Authorization: auth_token\r\n\r\n");
14914 const MockWrite kGetAuthThroughProxy(
14915 "GET http://www.example.com/ HTTP/1.1\r\n"
14916 "Host: www.example.com\r\n"
14917 "Proxy-Connection: keep-alive\r\n"
14918 "Authorization: auth_token\r\n\r\n");
14919 const MockWrite kGetAuthWithProxyAuth(
14920 "GET http://www.example.com/ HTTP/1.1\r\n"
14921 "Host: www.example.com\r\n"
14922 "Proxy-Connection: keep-alive\r\n"
14923 "Proxy-Authorization: auth_token\r\n"
14924 "Authorization: auth_token\r\n\r\n");
14925 const MockWrite kConnect(
14926 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714927 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514928 "Proxy-Connection: keep-alive\r\n\r\n");
14929 const MockWrite kConnectProxyAuth(
14930 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714931 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514932 "Proxy-Connection: keep-alive\r\n"
14933 "Proxy-Authorization: auth_token\r\n\r\n");
14934
14935 const MockRead kSuccess(
14936 "HTTP/1.1 200 OK\r\n"
14937 "Content-Type: text/html; charset=iso-8859-1\r\n"
14938 "Content-Length: 3\r\n\r\n"
14939 "Yes");
14940 const MockRead kFailure(
14941 "Should not be called.");
14942 const MockRead kServerChallenge(
14943 "HTTP/1.1 401 Unauthorized\r\n"
14944 "WWW-Authenticate: Mock realm=server\r\n"
14945 "Content-Type: text/html; charset=iso-8859-1\r\n"
14946 "Content-Length: 14\r\n\r\n"
14947 "Unauthorized\r\n");
14948 const MockRead kProxyChallenge(
14949 "HTTP/1.1 407 Unauthorized\r\n"
14950 "Proxy-Authenticate: Mock realm=proxy\r\n"
14951 "Proxy-Connection: close\r\n"
14952 "Content-Type: text/html; charset=iso-8859-1\r\n"
14953 "Content-Length: 14\r\n\r\n"
14954 "Unauthorized\r\n");
14955 const MockRead kProxyConnected(
14956 "HTTP/1.1 200 Connection Established\r\n\r\n");
14957
14958 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14959 // no constructors, but the C++ compiler on Windows warns about
14960 // unspecified data in compound literals. So, moved to using constructors,
14961 // and TestRound's created with the default constructor should not be used.
14962 struct TestRound {
14963 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514964 : expected_rv(ERR_UNEXPECTED),
14965 extra_write(nullptr),
14966 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314967 TestRound(const MockWrite& write_arg,
14968 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514969 int expected_rv_arg)
14970 : write(write_arg),
14971 read(read_arg),
14972 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514973 extra_write(nullptr),
14974 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514975 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14976 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114977 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514978 : write(write_arg),
14979 read(read_arg),
14980 expected_rv(expected_rv_arg),
14981 extra_write(extra_write_arg),
14982 extra_read(extra_read_arg) {
14983 }
14984 MockWrite write;
14985 MockRead read;
14986 int expected_rv;
14987 const MockWrite* extra_write;
14988 const MockRead* extra_read;
14989 };
14990
14991 static const int kNoSSL = 500;
14992
14993 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114994 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114995 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514996 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114997 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114998 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514999 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3115000 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1515001 int num_auth_rounds;
15002 int first_ssl_round;
asankae2257db2016-10-11 22:03:1615003 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1515004 } test_configs[] = {
asankac93076192016-10-03 15:46:0215005 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3115006 {__LINE__,
15007 nullptr,
asankac93076192016-10-03 15:46:0215008 AUTH_NONE,
15009 OK,
15010 kServer,
15011 AUTH_NONE,
15012 OK,
15013 1,
15014 kNoSSL,
15015 {TestRound(kGet, kSuccess, OK)}},
15016 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3115017 {__LINE__,
15018 nullptr,
asankac93076192016-10-03 15:46:0215019 AUTH_NONE,
15020 OK,
15021 kServer,
15022 AUTH_SYNC,
15023 OK,
15024 2,
15025 kNoSSL,
15026 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515027 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115028 {__LINE__,
15029 nullptr,
asankac93076192016-10-03 15:46:0215030 AUTH_NONE,
15031 OK,
15032 kServer,
15033 AUTH_SYNC,
15034 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615035 3,
15036 kNoSSL,
15037 {TestRound(kGet, kServerChallenge, OK),
15038 TestRound(kGet, kServerChallenge, OK),
15039 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115040 {__LINE__,
15041 nullptr,
asankae2257db2016-10-11 22:03:1615042 AUTH_NONE,
15043 OK,
15044 kServer,
15045 AUTH_SYNC,
15046 ERR_UNSUPPORTED_AUTH_SCHEME,
15047 2,
15048 kNoSSL,
15049 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115050 {__LINE__,
15051 nullptr,
asankae2257db2016-10-11 22:03:1615052 AUTH_NONE,
15053 OK,
15054 kServer,
15055 AUTH_SYNC,
15056 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
15057 2,
15058 kNoSSL,
15059 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115060 {__LINE__,
15061 kProxy,
asankae2257db2016-10-11 22:03:1615062 AUTH_SYNC,
15063 ERR_FAILED,
15064 kServer,
15065 AUTH_NONE,
15066 OK,
15067 2,
15068 kNoSSL,
15069 {TestRound(kGetProxy, kProxyChallenge, OK),
15070 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115071 {__LINE__,
15072 kProxy,
asankae2257db2016-10-11 22:03:1615073 AUTH_ASYNC,
15074 ERR_FAILED,
15075 kServer,
15076 AUTH_NONE,
15077 OK,
15078 2,
15079 kNoSSL,
15080 {TestRound(kGetProxy, kProxyChallenge, OK),
15081 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115082 {__LINE__,
15083 nullptr,
asankae2257db2016-10-11 22:03:1615084 AUTH_NONE,
15085 OK,
15086 kServer,
15087 AUTH_SYNC,
15088 ERR_FAILED,
asankac93076192016-10-03 15:46:0215089 2,
15090 kNoSSL,
15091 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615092 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115093 {__LINE__,
15094 nullptr,
asankae2257db2016-10-11 22:03:1615095 AUTH_NONE,
15096 OK,
15097 kServer,
15098 AUTH_ASYNC,
15099 ERR_FAILED,
15100 2,
15101 kNoSSL,
15102 {TestRound(kGet, kServerChallenge, OK),
15103 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115104 {__LINE__,
15105 nullptr,
asankac93076192016-10-03 15:46:0215106 AUTH_NONE,
15107 OK,
15108 kServer,
15109 AUTH_ASYNC,
15110 OK,
15111 2,
15112 kNoSSL,
15113 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515114 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115115 {__LINE__,
15116 nullptr,
asankac93076192016-10-03 15:46:0215117 AUTH_NONE,
15118 OK,
15119 kServer,
15120 AUTH_ASYNC,
15121 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615122 3,
asankac93076192016-10-03 15:46:0215123 kNoSSL,
15124 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615125 // The second round uses a HttpAuthHandlerMock that always succeeds.
15126 TestRound(kGet, kServerChallenge, OK),
15127 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215128 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115129 {__LINE__,
15130 kProxy,
asankac93076192016-10-03 15:46:0215131 AUTH_NONE,
15132 OK,
15133 kServer,
15134 AUTH_NONE,
15135 OK,
15136 1,
15137 kNoSSL,
15138 {TestRound(kGetProxy, kSuccess, OK)}},
15139 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115140 {__LINE__,
15141 kProxy,
asankac93076192016-10-03 15:46:0215142 AUTH_NONE,
15143 OK,
15144 kServer,
15145 AUTH_SYNC,
15146 OK,
15147 2,
15148 kNoSSL,
15149 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515150 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115151 {__LINE__,
15152 kProxy,
asankac93076192016-10-03 15:46:0215153 AUTH_NONE,
15154 OK,
15155 kServer,
15156 AUTH_SYNC,
15157 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615158 3,
asankac93076192016-10-03 15:46:0215159 kNoSSL,
15160 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615161 TestRound(kGetProxy, kServerChallenge, OK),
15162 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115163 {__LINE__,
15164 kProxy,
asankac93076192016-10-03 15:46:0215165 AUTH_NONE,
15166 OK,
15167 kServer,
15168 AUTH_ASYNC,
15169 OK,
15170 2,
15171 kNoSSL,
15172 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515173 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115174 {__LINE__,
15175 kProxy,
asankac93076192016-10-03 15:46:0215176 AUTH_NONE,
15177 OK,
15178 kServer,
15179 AUTH_ASYNC,
15180 ERR_INVALID_AUTH_CREDENTIALS,
15181 2,
15182 kNoSSL,
15183 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615184 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215185 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115186 {__LINE__,
15187 kProxy,
asankac93076192016-10-03 15:46:0215188 AUTH_SYNC,
15189 OK,
15190 kServer,
15191 AUTH_NONE,
15192 OK,
15193 2,
15194 kNoSSL,
15195 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515196 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115197 {__LINE__,
15198 kProxy,
asankac93076192016-10-03 15:46:0215199 AUTH_SYNC,
15200 ERR_INVALID_AUTH_CREDENTIALS,
15201 kServer,
15202 AUTH_NONE,
15203 OK,
15204 2,
15205 kNoSSL,
15206 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615207 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115208 {__LINE__,
15209 kProxy,
asankac93076192016-10-03 15:46:0215210 AUTH_ASYNC,
15211 OK,
15212 kServer,
15213 AUTH_NONE,
15214 OK,
15215 2,
15216 kNoSSL,
15217 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515218 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115219 {__LINE__,
15220 kProxy,
asankac93076192016-10-03 15:46:0215221 AUTH_ASYNC,
15222 ERR_INVALID_AUTH_CREDENTIALS,
15223 kServer,
15224 AUTH_NONE,
15225 OK,
15226 2,
15227 kNoSSL,
15228 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615229 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115230 {__LINE__,
15231 kProxy,
15232 AUTH_ASYNC,
15233 ERR_INVALID_AUTH_CREDENTIALS,
15234 kServer,
15235 AUTH_NONE,
15236 OK,
15237 3,
15238 kNoSSL,
15239 {TestRound(kGetProxy, kProxyChallenge, OK),
15240 TestRound(kGetProxy, kProxyChallenge, OK),
15241 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215242 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115243 {__LINE__,
15244 kProxy,
asankac93076192016-10-03 15:46:0215245 AUTH_SYNC,
15246 OK,
15247 kServer,
15248 AUTH_SYNC,
15249 OK,
15250 3,
15251 kNoSSL,
15252 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515253 TestRound(kGetProxyAuth, kServerChallenge, OK),
15254 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115255 {__LINE__,
15256 kProxy,
asankac93076192016-10-03 15:46:0215257 AUTH_SYNC,
15258 OK,
15259 kServer,
15260 AUTH_SYNC,
15261 ERR_INVALID_AUTH_CREDENTIALS,
15262 3,
15263 kNoSSL,
15264 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515265 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615266 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115267 {__LINE__,
15268 kProxy,
asankac93076192016-10-03 15:46:0215269 AUTH_ASYNC,
15270 OK,
15271 kServer,
15272 AUTH_SYNC,
15273 OK,
15274 3,
15275 kNoSSL,
15276 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515277 TestRound(kGetProxyAuth, kServerChallenge, OK),
15278 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115279 {__LINE__,
15280 kProxy,
asankac93076192016-10-03 15:46:0215281 AUTH_ASYNC,
15282 OK,
15283 kServer,
15284 AUTH_SYNC,
15285 ERR_INVALID_AUTH_CREDENTIALS,
15286 3,
15287 kNoSSL,
15288 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515289 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615290 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115291 {__LINE__,
15292 kProxy,
asankac93076192016-10-03 15:46:0215293 AUTH_SYNC,
15294 OK,
15295 kServer,
15296 AUTH_ASYNC,
15297 OK,
15298 3,
15299 kNoSSL,
15300 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515301 TestRound(kGetProxyAuth, kServerChallenge, OK),
15302 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115303 {__LINE__,
15304 kProxy,
15305 AUTH_SYNC,
15306 ERR_INVALID_AUTH_CREDENTIALS,
15307 kServer,
15308 AUTH_ASYNC,
15309 OK,
15310 4,
15311 kNoSSL,
15312 {TestRound(kGetProxy, kProxyChallenge, OK),
15313 TestRound(kGetProxy, kProxyChallenge, OK),
15314 TestRound(kGetProxyAuth, kServerChallenge, OK),
15315 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
15316 {__LINE__,
15317 kProxy,
asankac93076192016-10-03 15:46:0215318 AUTH_SYNC,
15319 OK,
15320 kServer,
15321 AUTH_ASYNC,
15322 ERR_INVALID_AUTH_CREDENTIALS,
15323 3,
15324 kNoSSL,
15325 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515326 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615327 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115328 {__LINE__,
15329 kProxy,
asankac93076192016-10-03 15:46:0215330 AUTH_ASYNC,
15331 OK,
15332 kServer,
15333 AUTH_ASYNC,
15334 OK,
15335 3,
15336 kNoSSL,
15337 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515338 TestRound(kGetProxyAuth, kServerChallenge, OK),
15339 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115340 {__LINE__,
15341 kProxy,
asankac93076192016-10-03 15:46:0215342 AUTH_ASYNC,
15343 OK,
15344 kServer,
15345 AUTH_ASYNC,
15346 ERR_INVALID_AUTH_CREDENTIALS,
15347 3,
15348 kNoSSL,
15349 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515350 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615351 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115352 {__LINE__,
15353 kProxy,
15354 AUTH_ASYNC,
15355 ERR_INVALID_AUTH_CREDENTIALS,
15356 kServer,
15357 AUTH_ASYNC,
15358 ERR_INVALID_AUTH_CREDENTIALS,
15359 4,
15360 kNoSSL,
15361 {TestRound(kGetProxy, kProxyChallenge, OK),
15362 TestRound(kGetProxy, kProxyChallenge, OK),
15363 TestRound(kGetProxyAuth, kServerChallenge, OK),
15364 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215365 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115366 {__LINE__,
15367 nullptr,
asankac93076192016-10-03 15:46:0215368 AUTH_NONE,
15369 OK,
15370 kSecureServer,
15371 AUTH_NONE,
15372 OK,
15373 1,
15374 0,
15375 {TestRound(kGet, kSuccess, OK)}},
15376 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115377 {__LINE__,
15378 nullptr,
asankac93076192016-10-03 15:46:0215379 AUTH_NONE,
15380 OK,
15381 kSecureServer,
15382 AUTH_SYNC,
15383 OK,
15384 2,
15385 0,
15386 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515387 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115388 {__LINE__,
15389 nullptr,
asankac93076192016-10-03 15:46:0215390 AUTH_NONE,
15391 OK,
15392 kSecureServer,
15393 AUTH_SYNC,
15394 ERR_INVALID_AUTH_CREDENTIALS,
15395 2,
15396 0,
asankae2257db2016-10-11 22:03:1615397 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115398 {__LINE__,
15399 nullptr,
asankac93076192016-10-03 15:46:0215400 AUTH_NONE,
15401 OK,
15402 kSecureServer,
15403 AUTH_ASYNC,
15404 OK,
15405 2,
15406 0,
15407 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515408 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115409 {__LINE__,
15410 nullptr,
asankac93076192016-10-03 15:46:0215411 AUTH_NONE,
15412 OK,
15413 kSecureServer,
15414 AUTH_ASYNC,
15415 ERR_INVALID_AUTH_CREDENTIALS,
15416 2,
15417 0,
asankae2257db2016-10-11 22:03:1615418 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215419 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115420 {__LINE__,
15421 kProxy,
asankac93076192016-10-03 15:46:0215422 AUTH_NONE,
15423 OK,
15424 kSecureServer,
15425 AUTH_NONE,
15426 OK,
15427 1,
15428 0,
15429 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
15430 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115431 {__LINE__,
15432 kProxy,
asankac93076192016-10-03 15:46:0215433 AUTH_NONE,
15434 OK,
15435 kSecureServer,
15436 AUTH_SYNC,
15437 OK,
15438 2,
15439 0,
15440 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515441 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115442 {__LINE__,
15443 kProxy,
asankac93076192016-10-03 15:46:0215444 AUTH_NONE,
15445 OK,
15446 kSecureServer,
15447 AUTH_SYNC,
15448 ERR_INVALID_AUTH_CREDENTIALS,
15449 2,
15450 0,
15451 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615452 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115453 {__LINE__,
15454 kProxy,
asankac93076192016-10-03 15:46:0215455 AUTH_NONE,
15456 OK,
15457 kSecureServer,
15458 AUTH_ASYNC,
15459 OK,
15460 2,
15461 0,
15462 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515463 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115464 {__LINE__,
15465 kProxy,
asankac93076192016-10-03 15:46:0215466 AUTH_NONE,
15467 OK,
15468 kSecureServer,
15469 AUTH_ASYNC,
15470 ERR_INVALID_AUTH_CREDENTIALS,
15471 2,
15472 0,
15473 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615474 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215475 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115476 {__LINE__,
15477 kProxy,
asankac93076192016-10-03 15:46:0215478 AUTH_SYNC,
15479 OK,
15480 kSecureServer,
15481 AUTH_NONE,
15482 OK,
15483 2,
15484 1,
15485 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515486 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115487 {__LINE__,
15488 kProxy,
asankac93076192016-10-03 15:46:0215489 AUTH_SYNC,
15490 ERR_INVALID_AUTH_CREDENTIALS,
15491 kSecureServer,
15492 AUTH_NONE,
15493 OK,
15494 2,
15495 kNoSSL,
15496 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615497 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115498 {__LINE__,
15499 kProxy,
asankae2257db2016-10-11 22:03:1615500 AUTH_SYNC,
15501 ERR_UNSUPPORTED_AUTH_SCHEME,
15502 kSecureServer,
15503 AUTH_NONE,
15504 OK,
15505 2,
15506 kNoSSL,
15507 {TestRound(kConnect, kProxyChallenge, OK),
15508 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115509 {__LINE__,
15510 kProxy,
asankae2257db2016-10-11 22:03:1615511 AUTH_SYNC,
15512 ERR_UNEXPECTED,
15513 kSecureServer,
15514 AUTH_NONE,
15515 OK,
15516 2,
15517 kNoSSL,
15518 {TestRound(kConnect, kProxyChallenge, OK),
15519 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115520 {__LINE__,
15521 kProxy,
asankac93076192016-10-03 15:46:0215522 AUTH_ASYNC,
15523 OK,
15524 kSecureServer,
15525 AUTH_NONE,
15526 OK,
15527 2,
15528 1,
15529 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515530 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115531 {__LINE__,
15532 kProxy,
asankac93076192016-10-03 15:46:0215533 AUTH_ASYNC,
15534 ERR_INVALID_AUTH_CREDENTIALS,
15535 kSecureServer,
15536 AUTH_NONE,
15537 OK,
15538 2,
15539 kNoSSL,
15540 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615541 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215542 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115543 {__LINE__,
15544 kProxy,
asankac93076192016-10-03 15:46:0215545 AUTH_SYNC,
15546 OK,
15547 kSecureServer,
15548 AUTH_SYNC,
15549 OK,
15550 3,
15551 1,
15552 {TestRound(kConnect, kProxyChallenge, OK),
15553 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15554 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515555 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115556 {__LINE__,
15557 kProxy,
asankac93076192016-10-03 15:46:0215558 AUTH_SYNC,
15559 OK,
15560 kSecureServer,
15561 AUTH_SYNC,
15562 ERR_INVALID_AUTH_CREDENTIALS,
15563 3,
15564 1,
15565 {TestRound(kConnect, kProxyChallenge, OK),
15566 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15567 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615568 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115569 {__LINE__,
15570 kProxy,
asankac93076192016-10-03 15:46:0215571 AUTH_ASYNC,
15572 OK,
15573 kSecureServer,
15574 AUTH_SYNC,
15575 OK,
15576 3,
15577 1,
15578 {TestRound(kConnect, kProxyChallenge, OK),
15579 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15580 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515581 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115582 {__LINE__,
15583 kProxy,
asankac93076192016-10-03 15:46:0215584 AUTH_ASYNC,
15585 OK,
15586 kSecureServer,
15587 AUTH_SYNC,
15588 ERR_INVALID_AUTH_CREDENTIALS,
15589 3,
15590 1,
15591 {TestRound(kConnect, kProxyChallenge, OK),
15592 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15593 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615594 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115595 {__LINE__,
15596 kProxy,
asankac93076192016-10-03 15:46:0215597 AUTH_SYNC,
15598 OK,
15599 kSecureServer,
15600 AUTH_ASYNC,
15601 OK,
15602 3,
15603 1,
15604 {TestRound(kConnect, kProxyChallenge, OK),
15605 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15606 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515607 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115608 {__LINE__,
15609 kProxy,
asankac93076192016-10-03 15:46:0215610 AUTH_SYNC,
15611 OK,
15612 kSecureServer,
15613 AUTH_ASYNC,
15614 ERR_INVALID_AUTH_CREDENTIALS,
15615 3,
15616 1,
15617 {TestRound(kConnect, kProxyChallenge, OK),
15618 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15619 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615620 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115621 {__LINE__,
15622 kProxy,
asankac93076192016-10-03 15:46:0215623 AUTH_ASYNC,
15624 OK,
15625 kSecureServer,
15626 AUTH_ASYNC,
15627 OK,
15628 3,
15629 1,
15630 {TestRound(kConnect, kProxyChallenge, OK),
15631 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15632 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515633 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115634 {__LINE__,
15635 kProxy,
asankac93076192016-10-03 15:46:0215636 AUTH_ASYNC,
15637 OK,
15638 kSecureServer,
15639 AUTH_ASYNC,
15640 ERR_INVALID_AUTH_CREDENTIALS,
15641 3,
15642 1,
15643 {TestRound(kConnect, kProxyChallenge, OK),
15644 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15645 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615646 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115647 {__LINE__,
15648 kProxy,
15649 AUTH_ASYNC,
15650 ERR_INVALID_AUTH_CREDENTIALS,
15651 kSecureServer,
15652 AUTH_ASYNC,
15653 ERR_INVALID_AUTH_CREDENTIALS,
15654 4,
15655 2,
15656 {TestRound(kConnect, kProxyChallenge, OK),
15657 TestRound(kConnect, kProxyChallenge, OK),
15658 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15659 &kServerChallenge),
15660 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515661 };
15662
asanka463ca4262016-11-16 02:34:3115663 for (const auto& test_config : test_configs) {
15664 SCOPED_TRACE(::testing::Message() << "Test config at "
15665 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815666 HttpAuthHandlerMock::Factory* auth_factory(
15667 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715668 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915669 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615670
15671 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515672 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115673 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815674 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15675 std::string auth_challenge = "Mock realm=proxy";
15676 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415677 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15678 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815679 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
Matt Menke618134b2020-05-22 02:12:2715680 empty_ssl_info, NetworkIsolationKey(),
15681 origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815682 auth_handler->SetGenerateExpectation(
15683 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115684 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815685 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15686 }
[email protected]044de0642010-06-17 10:42:1515687 }
15688 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015689 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515690 std::string auth_challenge = "Mock realm=server";
15691 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415692 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15693 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515694 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715695 empty_ssl_info, NetworkIsolationKey(),
15696 origin, NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515697 auth_handler->SetGenerateExpectation(
15698 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115699 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815700 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615701
15702 // The second handler always succeeds. It should only be used where there
15703 // are multiple auth sessions for server auth in the same network
15704 // transaction using the same auth scheme.
15705 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915706 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615707 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715708 empty_ssl_info, NetworkIsolationKey(),
15709 origin, NetLogWithSource());
asankae2257db2016-10-11 22:03:1615710 second_handler->SetGenerateExpectation(true, OK);
15711 auth_factory->AddMockHandler(second_handler.release(),
15712 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515713 }
15714 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915715 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615716 ConfiguredProxyResolutionService::CreateFixed(
15717 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515718 } else {
Bence Béky53a5aef2018-03-29 21:54:1215719 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615720 ConfiguredProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515721 }
15722
15723 HttpRequestInfo request;
15724 request.method = "GET";
15725 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1015726 request.traffic_annotation =
15727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515728
danakj1fd259a02016-04-16 03:17:0915729 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515730
rchcb68dc62015-05-21 04:45:3615731 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15732
15733 std::vector<std::vector<MockRead>> mock_reads(1);
15734 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515735 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215736 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515737 const TestRound& read_write_round = test_config.rounds[round];
15738
15739 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615740 mock_reads.back().push_back(read_write_round.read);
15741 mock_writes.back().push_back(read_write_round.write);
15742
15743 // kProxyChallenge uses Proxy-Connection: close which means that the
15744 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415745 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615746 mock_reads.push_back(std::vector<MockRead>());
15747 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515748 }
15749
rchcb68dc62015-05-21 04:45:3615750 if (read_write_round.extra_read) {
15751 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515752 }
rchcb68dc62015-05-21 04:45:3615753 if (read_write_round.extra_write) {
15754 mock_writes.back().push_back(*read_write_round.extra_write);
15755 }
[email protected]044de0642010-06-17 10:42:1515756
15757 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515758 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715759 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515760 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615761 }
[email protected]044de0642010-06-17 10:42:1515762
danakj1fd259a02016-04-16 03:17:0915763 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615764 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915765 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115766 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615767 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215768 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615769 }
15770
mmenkecc2298e2015-12-07 18:20:1815771 // Transaction must be created after DataProviders, so it's destroyed before
15772 // they are as well.
15773 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15774
rchcb68dc62015-05-21 04:45:3615775 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215776 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615777 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515778 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115779 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515780 int rv;
15781 if (round == 0) {
tfarina42834112016-09-22 13:38:2015782 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515783 } else {
[email protected]49639fa2011-12-20 23:22:4115784 rv = trans.RestartWithAuth(
15785 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515786 }
15787 if (rv == ERR_IO_PENDING)
15788 rv = callback.WaitForResult();
15789
15790 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615791 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015792 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515793 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515794 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15795 continue;
15796 }
15797 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815798 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515799 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815800 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615801 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515802 }
15803 }
[email protected]e5ae96a2010-04-14 20:12:4515804 }
15805}
15806
bncd16676a2016-07-20 16:23:0115807TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415808 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415809 HttpAuthHandlerMock::Factory* auth_factory(
15810 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715811 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215812 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615813 ConfiguredProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715814 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415815
15816 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15817 auth_handler->set_connection_based(true);
15818 std::string auth_challenge = "Mock realm=server";
15819 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415820 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15821 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915822 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415823 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715824 empty_ssl_info, NetworkIsolationKey(), origin,
15825 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815826 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415827
[email protected]c871bce92010-07-15 21:51:1415828 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515829 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415830 HttpRequestInfo request;
15831 request.method = "GET";
15832 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1015833 request.traffic_annotation =
15834 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715835
danakj1fd259a02016-04-16 03:17:0915836 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015837
15838 // Use a TCP Socket Pool with only one connection per group. This is used
15839 // to validate that the TCP socket is not released to the pool between
15840 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215841 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615842 CommonConnectJobParams common_connect_job_params(
15843 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815844 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915845 50, // Max sockets for pool
15846 1, // Max sockets per group
15847 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615848 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215849 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915850 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015851 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15852 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815853 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015854
bnc691fda62016-08-12 00:43:1615855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115856 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415857
15858 const MockWrite kGet(
15859 "GET / HTTP/1.1\r\n"
15860 "Host: www.example.com\r\n"
15861 "Connection: keep-alive\r\n\r\n");
15862 const MockWrite kGetAuth(
15863 "GET / HTTP/1.1\r\n"
15864 "Host: www.example.com\r\n"
15865 "Connection: keep-alive\r\n"
15866 "Authorization: auth_token\r\n\r\n");
15867
15868 const MockRead kServerChallenge(
15869 "HTTP/1.1 401 Unauthorized\r\n"
15870 "WWW-Authenticate: Mock realm=server\r\n"
15871 "Content-Type: text/html; charset=iso-8859-1\r\n"
15872 "Content-Length: 14\r\n\r\n"
15873 "Unauthorized\r\n");
15874 const MockRead kSuccess(
15875 "HTTP/1.1 200 OK\r\n"
15876 "Content-Type: text/html; charset=iso-8859-1\r\n"
15877 "Content-Length: 3\r\n\r\n"
15878 "Yes");
15879
15880 MockWrite writes[] = {
15881 // First round
15882 kGet,
15883 // Second round
15884 kGetAuth,
15885 // Third round
15886 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015887 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015888 kGetAuth,
15889 // Competing request
15890 kGet,
[email protected]c871bce92010-07-15 21:51:1415891 };
15892 MockRead reads[] = {
15893 // First round
15894 kServerChallenge,
15895 // Second round
15896 kServerChallenge,
15897 // Third round
[email protected]eca50e122010-09-11 14:03:3015898 kServerChallenge,
15899 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415900 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015901 // Competing response
15902 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415903 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115904 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715905 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415906
Matt Menkef6edce752019-03-19 17:21:5615907 const ClientSocketPool::GroupId kSocketGroup(
15908 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415909 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15910 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015911
15912 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415913 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015914 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415915 if (rv == ERR_IO_PENDING)
15916 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115917 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615918 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215919 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815920 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315921 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115922 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15923 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415924
[email protected]7ef4cbbb2011-02-06 11:19:1015925 // In between rounds, another request comes in for the same domain.
15926 // It should not be able to grab the TCP socket that trans has already
15927 // claimed.
bnc691fda62016-08-12 00:43:1615928 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115929 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015930 rv = trans_compete.Start(&request, callback_compete.callback(),
15931 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115932 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015933 // callback_compete.WaitForResult at this point would stall forever,
15934 // since the HttpNetworkTransaction does not release the request back to
15935 // the pool until after authentication completes.
15936
15937 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415938 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615939 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415940 if (rv == ERR_IO_PENDING)
15941 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115942 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615943 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215944 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815945 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315946 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115947 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15948 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415949
[email protected]7ef4cbbb2011-02-06 11:19:1015950 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415951 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615952 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415953 if (rv == ERR_IO_PENDING)
15954 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115955 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615956 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215957 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815958 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315959 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115960 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15961 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015962
[email protected]7ef4cbbb2011-02-06 11:19:1015963 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015964 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615965 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015966 if (rv == ERR_IO_PENDING)
15967 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115968 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615969 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215970 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815971 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315972 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015973
asanka463ca4262016-11-16 02:34:3115974 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15975 // auth handler should transition to a DONE state in concert with the remote
15976 // server. But that's not something we can test here with a mock handler.
15977 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15978 auth_handler->state());
15979
[email protected]7ef4cbbb2011-02-06 11:19:1015980 // Read the body since the fourth round was successful. This will also
15981 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415982 scoped_refptr<IOBufferWithSize> io_buf =
15983 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615984 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015985 if (rv == ERR_IO_PENDING)
15986 rv = callback.WaitForResult();
15987 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615988 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015989 EXPECT_EQ(0, rv);
15990 // There are still 0 idle sockets, since the trans_compete transaction
15991 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315992 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015993
15994 // The competing request can now finish. Wait for the headers and then
15995 // read the body.
15996 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115997 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615998 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015999 if (rv == ERR_IO_PENDING)
16000 rv = callback.WaitForResult();
16001 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1616002 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1016003 EXPECT_EQ(0, rv);
16004
16005 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4316006 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1416007}
16008
[email protected]65041fa2010-05-21 06:56:5316009// This tests the case that a request is issued via http instead of spdy after
16010// npn is negotiated.
bncd16676a2016-07-20 16:23:0116011TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5316012 HttpRequestInfo request;
16013 request.method = "GET";
bncce36dca22015-04-21 22:11:2316014 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016015 request.traffic_annotation =
16016 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5316017
16018 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2316019 MockWrite(
16020 "GET / HTTP/1.1\r\n"
16021 "Host: www.example.org\r\n"
16022 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5316023 };
16024
16025 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5216026 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4316027 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5216028 MockRead("\r\n"),
16029 MockRead("hello world"),
16030 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5316031 };
16032
[email protected]8ddf8322012-02-23 18:08:0616033 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616034 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5316035
[email protected]bb88e1d32013-05-03 23:11:0716036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5316037
Ryan Sleevib8d7ea02018-05-07 20:01:0116038 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716039 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5316040
[email protected]49639fa2011-12-20 23:22:4116041 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5316042
danakj1fd259a02016-04-16 03:17:0916043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616044 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5316045
tfarina42834112016-09-22 13:38:2016046 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5316047
robpercival214763f2016-07-01 23:27:0116048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16049 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5316050
bnc691fda62016-08-12 00:43:1616051 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216052 ASSERT_TRUE(response);
16053 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5316054 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16055
16056 std::string response_data;
bnc691fda62016-08-12 00:43:1616057 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5316058 EXPECT_EQ("hello world", response_data);
16059
16060 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216061 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5316062}
[email protected]26ef6582010-06-24 02:30:4716063
bnc55ff9da2015-08-19 18:42:3516064// Simulate the SSL handshake completing with an NPN negotiation followed by an
16065// immediate server closing of the socket.
16066// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0116067TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4716068 HttpRequestInfo request;
16069 request.method = "GET";
bncce36dca22015-04-21 22:11:2316070 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016071 request.traffic_annotation =
16072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4716073
[email protected]8ddf8322012-02-23 18:08:0616074 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616075 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716076 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4716077
Ryan Hamilton0239aac2018-05-19 00:03:1316078 spdy::SpdySerializedFrame req(
16079 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116080 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4716081
16082 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0616083 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4716084 };
16085
Ryan Sleevib8d7ea02018-05-07 20:01:0116086 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716087 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4716088
[email protected]49639fa2011-12-20 23:22:4116089 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4716090
danakj1fd259a02016-04-16 03:17:0916091 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616092 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4716093
tfarina42834112016-09-22 13:38:2016094 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116095 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16096 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4716097}
[email protected]65d34382010-07-01 18:12:2616098
[email protected]795cbf82013-07-22 09:37:2716099// A subclass of HttpAuthHandlerMock that records the request URL when
16100// it gets it. This is needed since the auth handler may get destroyed
16101// before we get a chance to query it.
16102class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
16103 public:
16104 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
16105
Chris Watkins7a41d3552017-12-01 02:13:2716106 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2716107
16108 protected:
dchengb03027d2014-10-21 12:00:2016109 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
16110 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0916111 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2016112 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2716113 *url_ = request->url;
16114 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0916115 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2716116 }
16117
16118 private:
16119 GURL* url_;
16120};
16121
[email protected]8e6441ca2010-08-19 05:56:3816122// Test that if we cancel the transaction as the connection is completing, that
16123// everything tears down correctly.
bncd16676a2016-07-20 16:23:0116124TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3816125 // Setup everything about the connection to complete synchronously, so that
16126 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
16127 // for is the callback from the HttpStreamRequest.
16128 // Then cancel the transaction.
16129 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3616130 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3816131 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0616132 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
16133 MockRead(SYNCHRONOUS, "hello world"),
16134 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3816135 };
16136
[email protected]8e6441ca2010-08-19 05:56:3816137 HttpRequestInfo request;
16138 request.method = "GET";
bncce36dca22015-04-21 22:11:2316139 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016140 request.traffic_annotation =
16141 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3816142
danakj1fd259a02016-04-16 03:17:0916143 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5816144 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916145 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2716146
Ryan Sleevib8d7ea02018-05-07 20:01:0116147 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3816148 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0716149 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3816150
[email protected]49639fa2011-12-20 23:22:4116151 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3816152
Matt Muellerd9342e3a2019-11-26 01:41:1416153 RecordingBoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4116154 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116155 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3816156 trans.reset(); // Cancel the transaction here.
16157
fdoray92e35a72016-06-10 15:54:5516158 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3016159}
16160
[email protected]ecab6e052014-05-16 14:58:1216161// Test that if a transaction is cancelled after receiving the headers, the
16162// stream is drained properly and added back to the socket pool. The main
16163// purpose of this test is to make sure that an HttpStreamParser can be read
16164// from after the HttpNetworkTransaction and the objects it owns have been
16165// deleted.
16166// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0116167TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1216168 MockRead data_reads[] = {
16169 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
16170 MockRead(ASYNC, "Content-Length: 2\r\n"),
16171 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
16172 MockRead(ASYNC, "1"),
16173 // 2 async reads are necessary to trigger a ReadResponseBody call after the
16174 // HttpNetworkTransaction has been deleted.
16175 MockRead(ASYNC, "2"),
16176 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
16177 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116178 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1216179 session_deps_.socket_factory->AddSocketDataProvider(&data);
16180
danakj1fd259a02016-04-16 03:17:0916181 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1216182
16183 {
16184 HttpRequestInfo request;
16185 request.method = "GET";
bncce36dca22015-04-21 22:11:2316186 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016187 request.traffic_annotation =
16188 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1216189
dcheng48459ac22014-08-26 00:46:4116190 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1216191 TestCompletionCallback callback;
16192
tfarina42834112016-09-22 13:38:2016193 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1216195 callback.WaitForResult();
16196
16197 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216198 ASSERT_TRUE(response);
16199 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1216200 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16201
16202 // The transaction and HttpRequestInfo are deleted.
16203 }
16204
16205 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5516206 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1216207
16208 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4116209 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1216210}
16211
[email protected]76a505b2010-08-25 06:23:0016212// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0116213TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916214 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616215 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916216 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416217 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716218 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916219 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016220
[email protected]76a505b2010-08-25 06:23:0016221 HttpRequestInfo request;
16222 request.method = "GET";
bncce36dca22015-04-21 22:11:2316223 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016224 request.traffic_annotation =
16225 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016226
16227 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2316228 MockWrite(
16229 "GET http://www.example.org/ HTTP/1.1\r\n"
16230 "Host: www.example.org\r\n"
16231 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016232 };
16233
16234 MockRead data_reads1[] = {
16235 MockRead("HTTP/1.1 200 OK\r\n"),
16236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16237 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616238 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016239 };
16240
Ryan Sleevib8d7ea02018-05-07 20:01:0116241 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716242 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0016243
[email protected]49639fa2011-12-20 23:22:4116244 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016245
bnc691fda62016-08-12 00:43:1616246 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216247 ConnectedHandler connected_handler;
16248 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016249
bnc691fda62016-08-12 00:43:1616250 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016252
16253 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116254 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0016255
bnc691fda62016-08-12 00:43:1616256 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216257 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016258
16259 EXPECT_TRUE(response->headers->IsKeepAlive());
16260 EXPECT_EQ(200, response->headers->response_code());
16261 EXPECT_EQ(100, response->headers->GetContentLength());
16262 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716263 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16264 HostPortPair::FromString("myproxy:70")),
16265 response->proxy_server);
[email protected]76a505b2010-08-25 06:23:0016266 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2016267
Titouan Rigoudyba507a882020-07-31 12:15:1516268 TransportInfo expected_transport;
16269 expected_transport.type = TransportType::kProxied;
16270 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16271 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
16272
[email protected]029c83b62013-01-24 05:28:2016273 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616274 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016275 TestLoadTimingNotReusedWithPac(load_timing_info,
16276 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0016277}
16278
16279// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0116280TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916281 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616282 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916283 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416284 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716285 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916286 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016287
[email protected]76a505b2010-08-25 06:23:0016288 HttpRequestInfo request;
16289 request.method = "GET";
bncce36dca22015-04-21 22:11:2316290 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016291 request.traffic_annotation =
16292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016293
16294 // Since we have proxy, should try to establish tunnel.
16295 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716296 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16297 "Host: www.example.org:443\r\n"
16298 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016299
rsleevidb16bb02015-11-12 23:47:1716300 MockWrite("GET / HTTP/1.1\r\n"
16301 "Host: www.example.org\r\n"
16302 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016303 };
16304
16305 MockRead data_reads1[] = {
16306 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16307
16308 MockRead("HTTP/1.1 200 OK\r\n"),
16309 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16310 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616311 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016312 };
16313
Ryan Sleevib8d7ea02018-05-07 20:01:0116314 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716315 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616316 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016318
[email protected]49639fa2011-12-20 23:22:4116319 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016320
bnc691fda62016-08-12 00:43:1616321 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216322 ConnectedHandler connected_handler;
16323 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016324
bnc691fda62016-08-12 00:43:1616325 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116326 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016327
16328 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116329 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416330 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016331 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016332 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16333 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016334 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016335 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016336 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16337 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016338
bnc691fda62016-08-12 00:43:1616339 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216340 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016341
16342 EXPECT_TRUE(response->headers->IsKeepAlive());
16343 EXPECT_EQ(200, response->headers->response_code());
16344 EXPECT_EQ(100, response->headers->GetContentLength());
16345 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16346 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716347 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16348 HostPortPair::FromString("myproxy:70")),
16349 response->proxy_server);
Titouan Rigoudyba507a882020-07-31 12:15:1516350
16351 TransportInfo expected_transport;
16352 expected_transport.type = TransportType::kProxied;
16353 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16354 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
[email protected]029c83b62013-01-24 05:28:2016355
16356 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616357 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016358 TestLoadTimingNotReusedWithPac(load_timing_info,
16359 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0016360}
16361
rsleevidb16bb02015-11-12 23:47:1716362// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
16363// literal host.
bncd16676a2016-07-20 16:23:0116364TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5916365 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616366 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916367 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416368 RecordingBoundTestNetLog log;
rsleevidb16bb02015-11-12 23:47:1716369 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1716371
16372 HttpRequestInfo request;
16373 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1516374 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1016375 request.traffic_annotation =
16376 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1716377
16378 // Since we have proxy, should try to establish tunnel.
16379 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1516380 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
16381 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1716382 "Proxy-Connection: keep-alive\r\n\r\n"),
16383
16384 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1516385 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1716386 "Connection: keep-alive\r\n\r\n"),
16387 };
16388
16389 MockRead data_reads1[] = {
16390 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16391
16392 MockRead("HTTP/1.1 200 OK\r\n"),
16393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16394 MockRead("Content-Length: 100\r\n\r\n"),
16395 MockRead(SYNCHRONOUS, OK),
16396 };
16397
Ryan Sleevib8d7ea02018-05-07 20:01:0116398 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1716399 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16400 SSLSocketDataProvider ssl(ASYNC, OK);
16401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16402
16403 TestCompletionCallback callback1;
16404
bnc691fda62016-08-12 00:43:1616405 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1716406
bnc691fda62016-08-12 00:43:1616407 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116408 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1716409
16410 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116411 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416412 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1716413 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016414 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16415 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716416 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016417 entries, pos,
16418 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16419 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716420
bnc691fda62016-08-12 00:43:1616421 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216422 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1716423
16424 EXPECT_TRUE(response->headers->IsKeepAlive());
16425 EXPECT_EQ(200, response->headers->response_code());
16426 EXPECT_EQ(100, response->headers->GetContentLength());
16427 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16428 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716429 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16430 HostPortPair::FromString("myproxy:70")),
16431 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1716432
16433 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616434 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1716435 TestLoadTimingNotReusedWithPac(load_timing_info,
16436 CONNECT_TIMING_HAS_SSL_TIMES);
16437}
16438
[email protected]76a505b2010-08-25 06:23:0016439// Test a basic HTTPS GET request through a proxy, but the server hangs up
16440// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0116441TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616442 session_deps_.proxy_resolution_service =
16443 ConfiguredProxyResolutionService::CreateFixed(
16444 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416445 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716446 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916447 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016448
[email protected]76a505b2010-08-25 06:23:0016449 HttpRequestInfo request;
16450 request.method = "GET";
bncce36dca22015-04-21 22:11:2316451 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016452 request.traffic_annotation =
16453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016454
16455 // Since we have proxy, should try to establish tunnel.
16456 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716457 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16458 "Host: www.example.org:443\r\n"
16459 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016460
rsleevidb16bb02015-11-12 23:47:1716461 MockWrite("GET / HTTP/1.1\r\n"
16462 "Host: www.example.org\r\n"
16463 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016464 };
16465
16466 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0016467 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616468 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0016469 };
16470
Ryan Sleevib8d7ea02018-05-07 20:01:0116471 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716472 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616473 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016475
[email protected]49639fa2011-12-20 23:22:4116476 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016477
bnc691fda62016-08-12 00:43:1616478 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5016479
bnc691fda62016-08-12 00:43:1616480 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016482
16483 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116484 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5416485 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016486 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016487 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16488 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016489 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016490 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016491 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16492 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016493}
16494
[email protected]749eefa82010-09-13 22:14:0316495// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0116496TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1316497 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4916498 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116499 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0316500
Raul Tambre94493c652019-03-11 17:18:3516501 spdy::SpdySerializedFrame resp(
16502 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316503 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0316504 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116505 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0316506 };
16507
Ryan Sleevib8d7ea02018-05-07 20:01:0116508 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716509 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0316510
[email protected]8ddf8322012-02-23 18:08:0616511 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616512 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716513 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0316514
danakj1fd259a02016-04-16 03:17:0916515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0316516
16517 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2316518 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4016519 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1116520 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3416521 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16522 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716523 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216524 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316525
16526 HttpRequestInfo request;
16527 request.method = "GET";
bncce36dca22015-04-21 22:11:2316528 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016529 request.traffic_annotation =
16530 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316531
bnc691fda62016-08-12 00:43:1616532 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316533
[email protected]41d64e82013-07-03 22:44:2616534 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016535 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116536 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16537 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316538}
16539
[email protected]73b8dd222010-11-11 19:55:2416540// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616541// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216542void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716543 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916544 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716545 request_info.url = GURL("https://www.example.com/");
16546 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916547 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016548 request_info.traffic_annotation =
16549 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716550
[email protected]8ddf8322012-02-23 18:08:0616551 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916552 MockWrite data_writes[] = {
16553 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416554 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116555 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716556 session_deps_.socket_factory->AddSocketDataProvider(&data);
16557 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416558
danakj1fd259a02016-04-16 03:17:0916559 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616560 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416561
[email protected]49639fa2011-12-20 23:22:4116562 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016563 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916564 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416565 rv = callback.WaitForResult();
16566 ASSERT_EQ(error, rv);
16567}
16568
bncd16676a2016-07-20 16:23:0116569TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416570 // Just check a grab bag of cert errors.
16571 static const int kErrors[] = {
16572 ERR_CERT_COMMON_NAME_INVALID,
16573 ERR_CERT_AUTHORITY_INVALID,
16574 ERR_CERT_DATE_INVALID,
16575 };
Avi Drissman4365a4782018-12-28 19:26:2416576 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616577 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16578 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416579 }
16580}
16581
[email protected]bd0b6772011-01-11 19:59:3016582// Ensure that a client certificate is removed from the SSL client auth
16583// cache when:
16584// 1) No proxy is involved.
16585// 2) TLS False Start is disabled.
16586// 3) The initial TLS handshake requests a client certificate.
16587// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116588TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916589 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716590 request_info.url = GURL("https://www.example.com/");
16591 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916592 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016593 request_info.traffic_annotation =
16594 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716595
David Benjamin1c4b6d012019-07-08 17:12:5716596 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116597 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016598
16599 // [ssl_]data1 contains the data for the first SSL handshake. When a
16600 // CertificateRequest is received for the first time, the handshake will
16601 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916602 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016603 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116605 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716606 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016607
16608 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16609 // False Start is not being used, the result of the SSL handshake will be
16610 // returned as part of the SSLClientSocket::Connect() call. This test
16611 // matches the result of a server sending a handshake_failure alert,
16612 // rather than a Finished message, because it requires a client
16613 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916614 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016615 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716616 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116617 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716618 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016619
16620 // [ssl_]data3 contains the data for the third SSL handshake. When a
16621 // connection to a server fails during an SSL handshake,
David Benjamin07a07d652020-02-26 22:26:5916622 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
16623 // enabled on some errors. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016624 // of the HttpNetworkTransaction. Because this test failure is due to
16625 // requiring a client certificate, this fallback handshake should also
16626 // fail.
ttuttle859dc7a2015-04-23 19:42:2916627 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
David Benjamin07a07d652020-02-26 22:26:5916628 ssl_data3.expected_disable_legacy_crypto = false;
[email protected]bd0b6772011-01-11 19:59:3016629 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116631 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716632 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016633
danakj1fd259a02016-04-16 03:17:0916634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016636
[email protected]bd0b6772011-01-11 19:59:3016637 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116638 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016639 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116640 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016641
16642 // Complete the SSL handshake, which should abort due to requiring a
16643 // client certificate.
16644 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116645 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016646
16647 // Indicate that no certificate should be supplied. From the perspective
16648 // of SSLClientCertCache, NULL is just as meaningful as a real
16649 // certificate, so this is the same as supply a
16650 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516651 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116652 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016653
16654 // Ensure the certificate was added to the client auth cache before
16655 // allowing the connection to continue restarting.
16656 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416657 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116658 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416659 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216660 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016661
16662 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716663 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16664 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016665 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116666 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016667
16668 // Ensure that the client certificate is removed from the cache on a
16669 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116670 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416671 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016672}
16673
16674// Ensure that a client certificate is removed from the SSL client auth
16675// cache when:
16676// 1) No proxy is involved.
16677// 2) TLS False Start is enabled.
16678// 3) The initial TLS handshake requests a client certificate.
16679// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116680TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916681 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716682 request_info.url = GURL("https://www.example.com/");
16683 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916684 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016685 request_info.traffic_annotation =
16686 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716687
David Benjamin1c4b6d012019-07-08 17:12:5716688 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116689 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016690
16691 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16692 // return successfully after reading up to the peer's Certificate message.
16693 // This is to allow the caller to call SSLClientSocket::Write(), which can
16694 // enqueue application data to be sent in the same packet as the
16695 // ChangeCipherSpec and Finished messages.
16696 // The actual handshake will be finished when SSLClientSocket::Read() is
16697 // called, which expects to process the peer's ChangeCipherSpec and
16698 // Finished messages. If there was an error negotiating with the peer,
16699 // such as due to the peer requiring a client certificate when none was
16700 // supplied, the alert sent by the peer won't be processed until Read() is
16701 // called.
16702
16703 // Like the non-False Start case, when a client certificate is requested by
16704 // the peer, the handshake is aborted during the Connect() call.
16705 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916706 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016707 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716708 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116709 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716710 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016711
16712 // When a client certificate is supplied, Connect() will not be aborted
16713 // when the peer requests the certificate. Instead, the handshake will
16714 // artificially succeed, allowing the caller to write the HTTP request to
16715 // the socket. The handshake messages are not processed until Read() is
16716 // called, which then detects that the handshake was aborted, due to the
16717 // peer sending a handshake_failure because it requires a client
16718 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916719 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016720 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916722 MockRead data2_reads[] = {
16723 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016724 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116725 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716726 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016727
16728 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716729 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16730 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916731 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016732 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116734 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716735 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016736
[email protected]80c75f682012-05-26 16:22:1716737 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16738 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916739 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716740 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716741 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116742 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716743 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716744
[email protected]7799de12013-05-30 05:52:5116745 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916746 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116747 ssl_data5.cert_request_info = cert_request.get();
16748 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116749 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116750 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16751
danakj1fd259a02016-04-16 03:17:0916752 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616753 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016754
[email protected]bd0b6772011-01-11 19:59:3016755 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116756 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016757 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116758 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016759
16760 // Complete the SSL handshake, which should abort due to requiring a
16761 // client certificate.
16762 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116763 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016764
16765 // Indicate that no certificate should be supplied. From the perspective
16766 // of SSLClientCertCache, NULL is just as meaningful as a real
16767 // certificate, so this is the same as supply a
16768 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516769 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116770 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016771
16772 // Ensure the certificate was added to the client auth cache before
16773 // allowing the connection to continue restarting.
16774 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416775 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116776 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416777 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216778 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016779
[email protected]bd0b6772011-01-11 19:59:3016780 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716781 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16782 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016783 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116784 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016785
16786 // Ensure that the client certificate is removed from the cache on a
16787 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116788 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416789 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016790}
16791
[email protected]8c405132011-01-11 22:03:1816792// Ensure that a client certificate is removed from the SSL client auth
16793// cache when:
16794// 1) An HTTPS proxy is involved.
16795// 3) The HTTPS proxy requests a client certificate.
16796// 4) The client supplies an invalid/unacceptable certificate for the
16797// proxy.
bncd16676a2016-07-20 16:23:0116798TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616799 session_deps_.proxy_resolution_service =
16800 ConfiguredProxyResolutionService::CreateFixed(
16801 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416802 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716803 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816804
David Benjamin3b94b0f2019-04-25 23:07:5216805 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116806 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816807
David Benjamin3b94b0f2019-04-25 23:07:5216808 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16809 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916810 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816811 requests[0].url = GURL("https://www.example.com/");
16812 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916813 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016814 requests[0].traffic_annotation =
16815 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816816
David Benjamin3b94b0f2019-04-25 23:07:5216817 // HTTPS requests are tunneled.
16818 MockWrite https_writes[] = {
16819 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16820 "Host: www.example.com:443\r\n"
16821 "Proxy-Connection: keep-alive\r\n\r\n"),
16822 };
16823
[email protected]8c405132011-01-11 22:03:1816824 requests[1].url = GURL("http://www.example.com/");
16825 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916826 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016827 requests[1].traffic_annotation =
16828 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816829
David Benjamin3b94b0f2019-04-25 23:07:5216830 // HTTP requests are not.
16831 MockWrite http_writes[] = {
16832 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16833 "Host: www.example.com\r\n"
16834 "Proxy-Connection: keep-alive\r\n\r\n"),
16835 };
[email protected]8c405132011-01-11 22:03:1816836
David Benjamin3b94b0f2019-04-25 23:07:5216837 // When the server rejects the client certificate, it will close the
16838 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16839 // TLS 1.2 with False Start), the error is returned out of the first Read().
16840 for (bool reject_in_connect : {true, false}) {
16841 SCOPED_TRACE(reject_in_connect);
16842 // Client certificate errors are typically signaled with
16843 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16844 // protocol error.
16845 for (Error reject_error :
16846 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16847 SCOPED_TRACE(reject_error);
16848 // Tunneled and non-tunneled requests are handled differently. Test both.
16849 for (const HttpRequestInfo& request : requests) {
16850 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816851
David Benjamin3b94b0f2019-04-25 23:07:5216852 session_deps_.socket_factory =
16853 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816854
David Benjamin3b94b0f2019-04-25 23:07:5216855 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
David Benjamin07a07d652020-02-26 22:26:5916856 // [ssl_]data[1-3].
David Benjamin3b94b0f2019-04-25 23:07:5216857 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16858 ssl_data1.cert_request_info = cert_request.get();
16859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16860 StaticSocketDataProvider data1;
16861 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816862
David Benjamin3b94b0f2019-04-25 23:07:5216863 base::Optional<SSLSocketDataProvider> ssl_data2;
16864 base::Optional<StaticSocketDataProvider> data2;
16865 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16866 if (reject_in_connect) {
16867 ssl_data2.emplace(ASYNC, reject_error);
16868 // There are no reads or writes.
16869 data2.emplace();
16870 } else {
16871 ssl_data2.emplace(ASYNC, OK);
16872 // We will get one Write() in before observing the error in Read().
16873 if (request.url.SchemeIsCryptographic()) {
16874 data2.emplace(error_in_read, https_writes);
16875 } else {
16876 data2.emplace(error_in_read, http_writes);
16877 }
16878 }
16879 ssl_data2->cert_request_info = cert_request.get();
David Benjamin3b94b0f2019-04-25 23:07:5216880 session_deps_.socket_factory->AddSSLSocketDataProvider(
16881 &ssl_data2.value());
16882 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816883
David Benjamin07a07d652020-02-26 22:26:5916884 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
16885 // connect twice.
16886 base::Optional<SSLSocketDataProvider> ssl_data3;
16887 base::Optional<StaticSocketDataProvider> data3;
16888 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
16889 ssl_data3.emplace(ASYNC, reject_error);
16890 data3.emplace(); // There are no reads or writes.
16891 ssl_data3->cert_request_info = cert_request.get();
16892 session_deps_.socket_factory->AddSSLSocketDataProvider(
16893 &ssl_data3.value());
16894 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
16895 }
16896
David Benjamin3b94b0f2019-04-25 23:07:5216897 std::unique_ptr<HttpNetworkSession> session =
16898 CreateSession(&session_deps_);
16899 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16900
16901 // Begin the SSL handshake with the proxy.
16902 TestCompletionCallback callback;
16903 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16904 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16905
16906 // Complete the SSL handshake, which should abort due to requiring a
16907 // client certificate.
16908 rv = callback.WaitForResult();
16909 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16910
16911 // Indicate that no certificate should be supplied. From the
16912 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16913 // real certificate, so this is the same as supply a
16914 // legitimate-but-unacceptable certificate.
16915 rv =
16916 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16917 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16918
16919 // Ensure the certificate was added to the client auth cache before
16920 // allowing the connection to continue restarting.
16921 scoped_refptr<X509Certificate> client_cert;
16922 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116923 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216924 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16925 ASSERT_FALSE(client_cert);
16926 // Ensure the certificate was NOT cached for the endpoint. This only
16927 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116928 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216929 HostPortPair("www.example.com", 443), &client_cert,
16930 &client_private_key));
16931
16932 // Restart the handshake. This will consume ssl_data2. The result code
16933 // is checked against what ssl_data2 should return.
16934 rv = callback.WaitForResult();
16935 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16936 IsError(reject_error)));
16937
16938 // Now that the new handshake has failed, ensure that the client
16939 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116940 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216941 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116942 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216943 HostPortPair("www.example.com", 443), &client_cert,
16944 &client_private_key));
16945 }
16946 }
[email protected]8c405132011-01-11 22:03:1816947 }
16948}
16949
David Benjamin1a0566082019-04-30 07:36:1916950// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16951// requests during a TLS renegotiation.
16952TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16953 HttpRequestInfo request_info;
16954 request_info.url = GURL("https://www.example.com/");
16955 request_info.method = "GET";
16956 request_info.load_flags = LOAD_NORMAL;
16957 request_info.traffic_annotation =
16958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16959
16960 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16961 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16962
16963 std::unique_ptr<FakeClientCertIdentity> identity =
16964 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16965 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16966 ASSERT_TRUE(identity);
16967
16968 // The first connection's handshake succeeds, but we get
16969 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16970 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16971 ssl_data1.cert_request_info = cert_request.get();
16972 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16973 MockWrite data1_writes[] = {
16974 MockWrite("GET / HTTP/1.1\r\n"
16975 "Host: www.example.com\r\n"
16976 "Connection: keep-alive\r\n\r\n"),
16977 };
16978 MockRead data1_reads[] = {
16979 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16980 };
16981 StaticSocketDataProvider data1(data1_reads, data1_writes);
16982 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16983
16984 // After supplying with certificate, we restart the request from the top,
16985 // which succeeds this time.
16986 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16987 ssl_data2.expected_send_client_cert = true;
16988 ssl_data2.expected_client_cert = identity->certificate();
16989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16990 MockWrite data2_writes[] = {
16991 MockWrite("GET / HTTP/1.1\r\n"
16992 "Host: www.example.com\r\n"
16993 "Connection: keep-alive\r\n\r\n"),
16994 };
16995 MockRead data2_reads[] = {
16996 MockRead("HTTP/1.1 200 OK\r\n"
16997 "Content-Length: 0\r\n\r\n"),
16998 };
16999 StaticSocketDataProvider data2(data2_reads, data2_writes);
17000 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17001
17002 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
17003 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
17004
17005 TestCompletionCallback callback;
17006 int rv = callback.GetResult(
17007 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
17008 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
17009
17010 rv = trans.RestartWithCertificate(identity->certificate(),
17011 identity->ssl_private_key(),
17012 callback.callback());
17013 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
17014
17015 // Ensure the certificate was added to the client auth cache
17016 // allowing the connection to continue restarting.
17017 scoped_refptr<X509Certificate> client_cert;
17018 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4117019 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1917020 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
17021 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
17022
17023 // Complete the handshake. The request now succeeds.
17024 rv = callback.WaitForResult();
17025 ASSERT_THAT(rv, IsError(OK));
17026 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
17027
17028 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4117029 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1917030 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
17031 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
17032}
17033
bncd16676a2016-07-20 16:23:0117034TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4617035 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1917036 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0917037 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617038
bnc032658ba2016-09-26 18:17:1517039 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617040
Ryan Hamilton0239aac2018-05-19 00:03:1317041 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917042 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817043 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317044 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717045 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617046 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117047 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617048 };
Ryan Hamilton0239aac2018-05-19 00:03:1317049 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517050 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317051 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117052 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317053 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517054 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317055 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117056 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617057 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117058 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17059 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317060 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617061 };
17062
eroman36d84e54432016-03-17 03:23:0217063 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217064 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117065 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717066 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617067
[email protected]aa22b242011-11-16 18:58:2917068 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617069 HttpRequestInfo request1;
17070 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317071 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617072 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017073 request1.traffic_annotation =
17074 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017075 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617076
tfarina42834112016-09-22 13:38:2017077 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117078 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17079 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617080
17081 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217082 ASSERT_TRUE(response);
17083 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217084 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617085
17086 std::string response_data;
robpercival214763f2016-07-01 23:27:0117087 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617088 EXPECT_EQ("hello!", response_data);
17089
bnca4d611d2016-09-22 19:55:3717090 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317091 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317092 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17093 base::nullopt);
robpercival214763f2016-07-01 23:27:0117094 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617095
17096 HttpRequestInfo request2;
17097 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717098 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617099 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017100 request2.traffic_annotation =
17101 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017102 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617103
tfarina42834112016-09-22 13:38:2017104 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117105 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17106 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617107
17108 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217109 ASSERT_TRUE(response);
17110 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217111 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617112 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217113 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117114 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617115 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617116}
17117
bncd16676a2016-07-20 16:23:0117118TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0217119 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1917120 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0917121 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0217122
bnc032658ba2016-09-26 18:17:1517123 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0217124
Ryan Hamilton0239aac2018-05-19 00:03:1317125 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917126 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817127 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317128 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717129 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0217130 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117131 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0217132 };
Ryan Hamilton0239aac2018-05-19 00:03:1317133 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517134 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317135 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117136 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317137 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517138 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317139 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117140 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0217141 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117142 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17143 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317144 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0217145 };
17146
eroman36d84e54432016-03-17 03:23:0217147 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217148 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117149 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717150 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0217151
17152 TestCompletionCallback callback;
17153 HttpRequestInfo request1;
17154 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317155 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0217156 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017157 request1.traffic_annotation =
17158 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017159 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217160
tfarina42834112016-09-22 13:38:2017161 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117162 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17163 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217164
17165 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217166 ASSERT_TRUE(response);
17167 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217168 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217169
17170 std::string response_data;
robpercival214763f2016-07-01 23:27:0117171 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217172 EXPECT_EQ("hello!", response_data);
17173
17174 HttpRequestInfo request2;
17175 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717176 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0217177 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017178 request2.traffic_annotation =
17179 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017180 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217181
tfarina42834112016-09-22 13:38:2017182 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117183 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17184 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217185
17186 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217187 ASSERT_TRUE(response);
17188 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217189 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217190 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217191 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117192 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217193 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0217194}
17195
bnc8016c1f2017-03-31 02:11:2917196// Regression test for https://crbug.com/546991.
17197// The server might not be able to serve an IP pooled request, and might send a
17198// 421 Misdirected Request response status to indicate this.
17199// HttpNetworkTransaction should reset the request and retry without IP pooling.
17200TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
17201 // Two hosts resolve to the same IP address.
17202 const std::string ip_addr = "1.2.3.4";
17203 IPAddress ip;
17204 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17205 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17206
Jeremy Roman0579ed62017-08-29 15:56:1917207 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2917208 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17209 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17210
17211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17212
17213 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317214 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2917215 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17216 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317217 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2917218 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317219 spdy::SpdySerializedFrame rst(
17220 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2917221 MockWrite writes1[] = {
17222 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17223 CreateMockWrite(rst, 6),
17224 };
17225
17226 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317227 spdy::SpdySerializedFrame resp1(
17228 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17229 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0117230 spdy::Http2HeaderBlock response_headers;
Ryan Hamilton0239aac2018-05-19 00:03:1317231 response_headers[spdy::kHttp2StatusHeader] = "421";
17232 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2917233 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
17234 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17235 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17236
17237 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117238 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2917239 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17240
17241 AddSSLSocketData();
17242
17243 // Retry the second request on a second connection.
17244 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317245 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2917246 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17247 MockWrite writes2[] = {
17248 CreateMockWrite(req3, 0),
17249 };
17250
Ryan Hamilton0239aac2018-05-19 00:03:1317251 spdy::SpdySerializedFrame resp3(
17252 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
17253 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2917254 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17255 MockRead(ASYNC, 0, 3)};
17256
17257 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117258 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2917259 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17260
17261 AddSSLSocketData();
17262
17263 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317264 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317265 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17266 base::nullopt);
bnc8016c1f2017-03-31 02:11:2917267 EXPECT_THAT(rv, IsOk());
17268
17269 HttpRequestInfo request1;
17270 request1.method = "GET";
17271 request1.url = GURL("https://www.example.org/");
17272 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017273 request1.traffic_annotation =
17274 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917275 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17276
Eric Orthf4db66a2019-02-19 21:35:3317277 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2917278 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17279 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17280 rv = callback.WaitForResult();
17281 EXPECT_THAT(rv, IsOk());
17282
17283 const HttpResponseInfo* response = trans1.GetResponseInfo();
17284 ASSERT_TRUE(response);
17285 ASSERT_TRUE(response->headers);
17286 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17287 EXPECT_TRUE(response->was_fetched_via_spdy);
17288 EXPECT_TRUE(response->was_alpn_negotiated);
17289 std::string response_data;
17290 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17291 EXPECT_EQ("hello!", response_data);
17292
17293 HttpRequestInfo request2;
17294 request2.method = "GET";
17295 request2.url = GURL("https://mail.example.org/");
17296 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017297 request2.traffic_annotation =
17298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917299 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17300
Matt Muellerd9342e3a2019-11-26 01:41:1417301 RecordingBoundTestNetLog log;
bnc8016c1f2017-03-31 02:11:2917302 rv = trans2.Start(&request2, callback.callback(), log.bound());
17303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17304 rv = callback.WaitForResult();
17305 EXPECT_THAT(rv, IsOk());
17306
17307 response = trans2.GetResponseInfo();
17308 ASSERT_TRUE(response);
17309 ASSERT_TRUE(response->headers);
17310 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17311 EXPECT_TRUE(response->was_fetched_via_spdy);
17312 EXPECT_TRUE(response->was_alpn_negotiated);
17313 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17314 EXPECT_EQ("hello!", response_data);
17315
Eric Roman79cc7552019-07-19 02:17:5417316 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5917317 ExpectLogContainsSomewhere(
17318 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2917319 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5917320}
17321
17322// Test that HTTP 421 responses are properly returned to the caller if received
17323// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
17324// portions of the response.
17325TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
17326 // Two hosts resolve to the same IP address.
17327 const std::string ip_addr = "1.2.3.4";
17328 IPAddress ip;
17329 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17330 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17331
Jeremy Roman0579ed62017-08-29 15:56:1917332 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5917333 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17334 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17335
17336 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17337
17338 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317339 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5917340 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17341 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317342 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5917343 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317344 spdy::SpdySerializedFrame rst(
17345 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5917346 MockWrite writes1[] = {
17347 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17348 CreateMockWrite(rst, 6),
17349 };
17350
17351 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317352 spdy::SpdySerializedFrame resp1(
17353 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17354 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0117355 spdy::Http2HeaderBlock response_headers;
Ryan Hamilton0239aac2018-05-19 00:03:1317356 response_headers[spdy::kHttp2StatusHeader] = "421";
17357 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5917358 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
17359 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17360 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17361
17362 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117363 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5917364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17365
17366 AddSSLSocketData();
17367
17368 // Retry the second request on a second connection. It returns 421 Misdirected
17369 // Retry again.
17370 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317371 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5917372 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17373 MockWrite writes2[] = {
17374 CreateMockWrite(req3, 0),
17375 };
17376
Ryan Hamilton0239aac2018-05-19 00:03:1317377 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5917378 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1317379 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5917380 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17381 MockRead(ASYNC, 0, 3)};
17382
17383 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117384 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5917385 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17386
17387 AddSSLSocketData();
17388
17389 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317390 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317391 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17392 base::nullopt);
davidbence688ae2017-05-04 15:12:5917393 EXPECT_THAT(rv, IsOk());
17394
17395 HttpRequestInfo request1;
17396 request1.method = "GET";
17397 request1.url = GURL("https://www.example.org/");
17398 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017399 request1.traffic_annotation =
17400 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917401 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17402
Eric Orthf4db66a2019-02-19 21:35:3317403 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5917404 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17405 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17406 rv = callback.WaitForResult();
17407 EXPECT_THAT(rv, IsOk());
17408
17409 const HttpResponseInfo* response = trans1.GetResponseInfo();
17410 ASSERT_TRUE(response);
17411 ASSERT_TRUE(response->headers);
17412 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17413 EXPECT_TRUE(response->was_fetched_via_spdy);
17414 EXPECT_TRUE(response->was_alpn_negotiated);
17415 std::string response_data;
17416 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17417 EXPECT_EQ("hello!", response_data);
17418
17419 HttpRequestInfo request2;
17420 request2.method = "GET";
17421 request2.url = GURL("https://mail.example.org/");
17422 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017423 request2.traffic_annotation =
17424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917425 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17426
Matt Muellerd9342e3a2019-11-26 01:41:1417427 RecordingBoundTestNetLog log;
davidbence688ae2017-05-04 15:12:5917428 rv = trans2.Start(&request2, callback.callback(), log.bound());
17429 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17430 rv = callback.WaitForResult();
17431 EXPECT_THAT(rv, IsOk());
17432
17433 // After a retry, the 421 Misdirected Request is reported back up to the
17434 // caller.
17435 response = trans2.GetResponseInfo();
17436 ASSERT_TRUE(response);
17437 ASSERT_TRUE(response->headers);
17438 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
17439 EXPECT_TRUE(response->was_fetched_via_spdy);
17440 EXPECT_TRUE(response->was_alpn_negotiated);
17441 EXPECT_TRUE(response->ssl_info.cert);
17442 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17443 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2917444}
17445
bncd16676a2016-07-20 16:23:0117446TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1317447 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3417448 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
17449 session_deps_.host_resolver =
17450 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0917451 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617452
bnc032658ba2016-09-26 18:17:1517453 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617454
Ryan Hamilton0239aac2018-05-19 00:03:1317455 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917456 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817457 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317458 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717459 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617460 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117461 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617462 };
Ryan Hamilton0239aac2018-05-19 00:03:1317463 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517464 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317465 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117466 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317467 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517468 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317469 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117470 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617471 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117472 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17473 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317474 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617475 };
17476
eroman36d84e54432016-03-17 03:23:0217477 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217478 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117479 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717480 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617481
[email protected]aa22b242011-11-16 18:58:2917482 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617483 HttpRequestInfo request1;
17484 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317485 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617486 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017487 request1.traffic_annotation =
17488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017489 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617490
tfarina42834112016-09-22 13:38:2017491 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17493 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617494
17495 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217496 ASSERT_TRUE(response);
17497 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217498 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617499
17500 std::string response_data;
robpercival214763f2016-07-01 23:27:0117501 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617502 EXPECT_EQ("hello!", response_data);
17503
17504 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317505 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317506 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17507 base::nullopt);
robpercival214763f2016-07-01 23:27:0117508 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617509
17510 HttpRequestInfo request2;
17511 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717512 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617513 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017514 request2.traffic_annotation =
17515 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017516 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617517
tfarina42834112016-09-22 13:38:2017518 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17520 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617521
17522 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217523 ASSERT_TRUE(response);
17524 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217525 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617526 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217527 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117528 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617529 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617530}
17531
bncd16676a2016-07-20 16:23:0117532TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317533 const std::string https_url = "https://www.example.org:8080/";
17534 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417535
17536 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317537 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917538 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417539
17540 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117541 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417542 };
17543
Raul Tambre94493c652019-03-11 17:18:3517544 spdy::SpdySerializedFrame resp1(
17545 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317546 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117547 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917548 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417549
Ryan Sleevib8d7ea02018-05-07 20:01:0117550 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417551 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717552 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417553
17554 // HTTP GET for the HTTP URL
17555 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317556 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417557 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317558 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417559 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417560 };
17561
17562 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317563 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17564 MockRead(ASYNC, 2, "hello"),
17565 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417566 };
17567
Ryan Sleevib8d7ea02018-05-07 20:01:0117568 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417569
[email protected]8450d722012-07-02 19:14:0417570 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617571 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717572 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17573 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17574 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417575
danakj1fd259a02016-04-16 03:17:0917576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417577
17578 // Start the first transaction to set up the SpdySession
17579 HttpRequestInfo request1;
17580 request1.method = "GET";
17581 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417582 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017583 request1.traffic_annotation =
17584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017585 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417586 TestCompletionCallback callback1;
17587 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017588 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517589 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417590
robpercival214763f2016-07-01 23:27:0117591 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417592 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17593
17594 // Now, start the HTTP request
17595 HttpRequestInfo request2;
17596 request2.method = "GET";
17597 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417598 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017599 request2.traffic_annotation =
17600 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017601 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417602 TestCompletionCallback callback2;
17603 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017604 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517605 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417606
robpercival214763f2016-07-01 23:27:0117607 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417608 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17609}
17610
bnc5452e2a2015-05-08 16:27:4217611// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17612// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117613TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517614 url::SchemeHostPort server("https", "www.example.org", 443);
17615 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217616
bnc8bef8da22016-05-30 01:28:2517617 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217618 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617619 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17621
17622 // No data should be read from the alternative, because HTTP/1.1 is
17623 // negotiated.
17624 StaticSocketDataProvider data;
17625 session_deps_.socket_factory->AddSocketDataProvider(&data);
17626
17627 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617628 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217629 // mocked. This way the request relies on the alternate Job.
17630 StaticSocketDataProvider data_refused;
17631 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17632 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17633
zhongyi3d4a55e72016-04-22 20:36:4617634 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917635 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017636 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217637 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117638 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217639 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117640 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717641 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217642
bnc5452e2a2015-05-08 16:27:4217643 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617644 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217645 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517646 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1017647 request.traffic_annotation =
17648 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217649 TestCompletionCallback callback;
17650
17651 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217652 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017653 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217654 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217655}
17656
bnc40448a532015-05-11 19:13:1417657// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617658// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417659// succeeds, the request should succeed, even if the latter fails because
17660// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117661TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517662 url::SchemeHostPort server("https", "www.example.org", 443);
17663 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417664
17665 // Negotiate HTTP/1.1 with alternative.
17666 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617667 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417668 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17669
17670 // No data should be read from the alternative, because HTTP/1.1 is
17671 // negotiated.
17672 StaticSocketDataProvider data;
17673 session_deps_.socket_factory->AddSocketDataProvider(&data);
17674
zhongyi3d4a55e72016-04-22 20:36:4617675 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417676 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617677 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417678 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17679
17680 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517681 MockWrite("GET / HTTP/1.1\r\n"
17682 "Host: www.example.org\r\n"
17683 "Connection: keep-alive\r\n\r\n"),
17684 MockWrite("GET /second HTTP/1.1\r\n"
17685 "Host: www.example.org\r\n"
17686 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417687 };
17688
17689 MockRead http_reads[] = {
17690 MockRead("HTTP/1.1 200 OK\r\n"),
17691 MockRead("Content-Type: text/html\r\n"),
17692 MockRead("Content-Length: 6\r\n\r\n"),
17693 MockRead("foobar"),
17694 MockRead("HTTP/1.1 200 OK\r\n"),
17695 MockRead("Content-Type: text/html\r\n"),
17696 MockRead("Content-Length: 7\r\n\r\n"),
17697 MockRead("another"),
17698 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117699 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417700 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17701
zhongyi3d4a55e72016-04-22 20:36:4617702 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917703 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017704 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417705 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117706 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217707 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117708 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717709 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417710
17711 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17712 HttpRequestInfo request1;
17713 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517714 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417715 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017716 request1.traffic_annotation =
17717 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417718 TestCompletionCallback callback1;
17719
tfarina42834112016-09-22 13:38:2017720 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417721 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117722 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417723
17724 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217725 ASSERT_TRUE(response1);
17726 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417727 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17728
17729 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117730 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417731 EXPECT_EQ("foobar", response_data1);
17732
17733 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17734 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517735 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17736 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417737
zhongyi3d4a55e72016-04-22 20:36:4617738 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417739 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617740 // to server.
bnc40448a532015-05-11 19:13:1417741 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17742 HttpRequestInfo request2;
17743 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517744 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417745 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017746 request2.traffic_annotation =
17747 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417748 TestCompletionCallback callback2;
17749
tfarina42834112016-09-22 13:38:2017750 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417751 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117752 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417753
17754 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217755 ASSERT_TRUE(response2);
17756 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417757 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17758
17759 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117760 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417761 EXPECT_EQ("another", response_data2);
17762}
17763
bnc5452e2a2015-05-08 16:27:4217764// Alternative service requires HTTP/2 (or SPDY), but there is already a
17765// HTTP/1.1 socket open to the alternative server. That socket should not be
17766// used.
bncd16676a2016-07-20 16:23:0117767TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617768 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217769 HostPortPair alternative("alternative.example.org", 443);
17770 std::string origin_url = "https://origin.example.org:443";
17771 std::string alternative_url = "https://alternative.example.org:443";
17772
17773 // Negotiate HTTP/1.1 with alternative.example.org.
17774 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617775 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17777
17778 // HTTP/1.1 data for |request1| and |request2|.
17779 MockWrite http_writes[] = {
17780 MockWrite(
17781 "GET / HTTP/1.1\r\n"
17782 "Host: alternative.example.org\r\n"
17783 "Connection: keep-alive\r\n\r\n"),
17784 MockWrite(
17785 "GET / HTTP/1.1\r\n"
17786 "Host: alternative.example.org\r\n"
17787 "Connection: keep-alive\r\n\r\n"),
17788 };
17789
17790 MockRead http_reads[] = {
17791 MockRead(
17792 "HTTP/1.1 200 OK\r\n"
17793 "Content-Type: text/html; charset=iso-8859-1\r\n"
17794 "Content-Length: 40\r\n\r\n"
17795 "first HTTP/1.1 response from alternative"),
17796 MockRead(
17797 "HTTP/1.1 200 OK\r\n"
17798 "Content-Type: text/html; charset=iso-8859-1\r\n"
17799 "Content-Length: 41\r\n\r\n"
17800 "second HTTP/1.1 response from alternative"),
17801 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117802 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217803 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17804
17805 // This test documents that an alternate Job should not pool to an already
17806 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617807 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217808 StaticSocketDataProvider data_refused;
17809 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17810 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17811
zhongyi3d4a55e72016-04-22 20:36:4617812 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017814 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217815 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117816 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217817 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117818 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717819 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217820
17821 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217822 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617823 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217824 request1.method = "GET";
17825 request1.url = GURL(alternative_url);
17826 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017827 request1.traffic_annotation =
17828 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217829 TestCompletionCallback callback1;
17830
tfarina42834112016-09-22 13:38:2017831 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117832 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617833 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217834 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217835 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217836 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217837 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217838 EXPECT_FALSE(response1->was_fetched_via_spdy);
17839 std::string response_data1;
bnc691fda62016-08-12 00:43:1617840 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217841 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17842
17843 // Request for origin.example.org, which has an alternative service. This
17844 // will start two Jobs: the alternative looks for connections to pool to,
17845 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617846 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217847 // this request fails.
bnc5452e2a2015-05-08 16:27:4217848 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617849 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217850 request2.method = "GET";
17851 request2.url = GURL(origin_url);
17852 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017853 request2.traffic_annotation =
17854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217855 TestCompletionCallback callback2;
17856
tfarina42834112016-09-22 13:38:2017857 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117858 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217859
17860 // Another transaction to alternative. This is to test that the HTTP/1.1
17861 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217862 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617863 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217864 request3.method = "GET";
17865 request3.url = GURL(alternative_url);
17866 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017867 request3.traffic_annotation =
17868 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217869 TestCompletionCallback callback3;
17870
tfarina42834112016-09-22 13:38:2017871 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117872 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617873 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217874 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217875 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217876 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217877 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217878 EXPECT_FALSE(response3->was_fetched_via_spdy);
17879 std::string response_data3;
bnc691fda62016-08-12 00:43:1617880 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217881 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17882}
17883
bncd16676a2016-07-20 16:23:0117884TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317885 const std::string https_url = "https://www.example.org:8080/";
17886 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417887
rdsmithebb50aa2015-11-12 03:44:3817888 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117889 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817890
[email protected]8450d722012-07-02 19:14:0417891 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317892 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417893 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17894 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17895 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317896 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917897 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317898 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217899 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917900
17901 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Bence Béky4c325e52020-10-22 20:48:0117902 spdy::Http2HeaderBlock req2_block;
Ryan Hamilton0239aac2018-05-19 00:03:1317903 req2_block[spdy::kHttp2MethodHeader] = "GET";
17904 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17905 req2_block[spdy::kHttp2SchemeHeader] = "http";
17906 req2_block[spdy::kHttp2PathHeader] = "/";
17907 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517908 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417909
17910 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117911 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17912 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417913 };
17914
Ryan Hamilton0239aac2018-05-19 00:03:1317915 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517916 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317917 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517918 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317919 spdy::SpdySerializedFrame body1(
17920 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17921 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817922 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317923 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817924 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517925 spdy::SpdySerializedFrame resp2(
17926 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317927 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317928 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117929 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317930 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117931 CreateMockRead(wrapped_resp1, 4),
17932 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317933 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117934 CreateMockRead(resp2, 8),
17935 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317936 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17937 };
[email protected]8450d722012-07-02 19:14:0417938
Ryan Sleevib8d7ea02018-05-07 20:01:0117939 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417940 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717941 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417942
Lily Houghton8c2f97d2018-01-22 05:06:5917943 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617944 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4917945 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1417946 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717947 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417948 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617949 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317950 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417951 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617952 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17954 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417955
danakj1fd259a02016-04-16 03:17:0917956 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417957
17958 // Start the first transaction to set up the SpdySession
17959 HttpRequestInfo request1;
17960 request1.method = "GET";
17961 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417962 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017963 request1.traffic_annotation =
17964 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017965 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417966 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017967 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417968
mmenke666a6fea2015-12-19 04:16:3317969 // This pause is a hack to avoid running into https://crbug.com/497228.
17970 data1.RunUntilPaused();
17971 base::RunLoop().RunUntilIdle();
17972 data1.Resume();
robpercival214763f2016-07-01 23:27:0117973 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417974 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17975
[email protected]f6c63db52013-02-02 00:35:2217976 LoadTimingInfo load_timing_info1;
17977 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17978 TestLoadTimingNotReusedWithPac(load_timing_info1,
17979 CONNECT_TIMING_HAS_SSL_TIMES);
17980
mmenke666a6fea2015-12-19 04:16:3317981 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417982 HttpRequestInfo request2;
17983 request2.method = "GET";
17984 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417985 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017986 request2.traffic_annotation =
17987 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017988 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417989 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017990 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417991
mmenke666a6fea2015-12-19 04:16:3317992 // This pause is a hack to avoid running into https://crbug.com/497228.
17993 data1.RunUntilPaused();
17994 base::RunLoop().RunUntilIdle();
17995 data1.Resume();
robpercival214763f2016-07-01 23:27:0117996 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317997
[email protected]8450d722012-07-02 19:14:0417998 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217999
18000 LoadTimingInfo load_timing_info2;
18001 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
18002 // The established SPDY sessions is considered reused by the HTTP request.
18003 TestLoadTimingReusedWithPac(load_timing_info2);
18004 // HTTP requests over a SPDY session should have a different connection
18005 // socket_log_id than requests over a tunnel.
18006 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0418007}
18008
[email protected]2d88e7d2012-07-19 17:55:1718009// Test that in the case where we have a SPDY session to a SPDY proxy
18010// that we do not pool other origins that resolve to the same IP when
18011// the certificate does not match the new origin.
18012// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0118013TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2318014 const std::string url1 = "http://www.example.org/";
18015 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1718016 const std::string ip_addr = "1.2.3.4";
18017
rdsmithebb50aa2015-11-12 03:44:3818018 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0118019 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3818020
[email protected]2d88e7d2012-07-19 17:55:1718021 // SPDY GET for HTTP URL (through SPDY proxy)
Bence Béky4c325e52020-10-22 20:48:0118022 spdy::Http2HeaderBlock headers(
bncce36dca22015-04-21 22:11:2318023 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1318024 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1518025 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1718026
18027 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4118028 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1718029 };
18030
Raul Tambre94493c652019-03-11 17:18:3518031 spdy::SpdySerializedFrame resp1(
18032 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318033 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1718034 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4118035 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
18036 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1718037 };
18038
Ryan Sleevib8d7ea02018-05-07 20:01:0118039 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3218040 IPAddress ip;
martijn654c8c42016-02-10 22:10:5918041 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1718042 IPEndPoint peer_addr = IPEndPoint(ip, 443);
18043 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3318044 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1718045
18046 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1318047 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4918048 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1718049
18050 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4118051 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1718052 };
18053
Ryan Hamilton0239aac2018-05-19 00:03:1318054 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3518055 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318056 spdy::SpdySerializedFrame body2(
18057 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4118058 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3318059 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1718060
Ryan Sleevib8d7ea02018-05-07 20:01:0118061 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1718062 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3318063 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1718064
18065 // Set up a proxy config that sends HTTP requests to a proxy, and
18066 // all others direct.
18067 ProxyConfig proxy_config;
18068 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4918069 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5618070 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4918071 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18072 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0918073 nullptr, nullptr, /*quick_check_enabled=*/true);
[email protected]2d88e7d2012-07-19 17:55:1718074
bncce36dca22015-04-21 22:11:2318075 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3618076 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1718077 // Load a valid cert. Note, that this does not need to
18078 // be valid for proxy because the MockSSLClientSocket does
18079 // not actually verify it. But SpdySession will use this
18080 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4918081 ssl1.ssl_info.cert =
18082 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
18083 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3318084 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18085 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1718086
18087 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3618088 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3318089 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18090 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1718091
Jeremy Roman0579ed62017-08-29 15:56:1918092 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2318093 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0718094 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1718095
danakj1fd259a02016-04-16 03:17:0918096 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1718097
18098 // Start the first transaction to set up the SpdySession
18099 HttpRequestInfo request1;
18100 request1.method = "GET";
18101 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1718102 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018103 request1.traffic_annotation =
18104 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018105 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718106 TestCompletionCallback callback1;
18107 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018108 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3318109 // This pause is a hack to avoid running into https://crbug.com/497228.
18110 data1.RunUntilPaused();
18111 base::RunLoop().RunUntilIdle();
18112 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1718113
robpercival214763f2016-07-01 23:27:0118114 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718115 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
18116
18117 // Now, start the HTTP request
18118 HttpRequestInfo request2;
18119 request2.method = "GET";
18120 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1718121 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018122 request2.traffic_annotation =
18123 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018124 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718125 TestCompletionCallback callback2;
18126 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018127 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5518128 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1718129
18130 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0118131 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718132 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18133}
18134
[email protected]85f97342013-04-17 06:12:2418135// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
18136// error) in SPDY session, removes the socket from pool and closes the SPDY
18137// session. Verify that new url's from the same HttpNetworkSession (and a new
18138// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0118139TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2318140 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2418141
18142 MockRead reads1[] = {
18143 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
18144 };
18145
Ryan Sleevib8d7ea02018-05-07 20:01:0118146 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2418147
Ryan Hamilton0239aac2018-05-19 00:03:1318148 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4918149 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2418150 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4118151 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2418152 };
18153
Raul Tambre94493c652019-03-11 17:18:3518154 spdy::SpdySerializedFrame resp2(
18155 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318156 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2418157 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4118158 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
18159 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2418160 };
18161
Ryan Sleevib8d7ea02018-05-07 20:01:0118162 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2418163
[email protected]85f97342013-04-17 06:12:2418164 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618165 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018166 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18167 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2418168
18169 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618170 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18172 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2418173
danakj1fd259a02016-04-16 03:17:0918174 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5018175 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2418176
18177 // Start the first transaction to set up the SpdySession and verify that
18178 // connection was closed.
18179 HttpRequestInfo request1;
18180 request1.method = "GET";
18181 request1.url = GURL(https_url);
18182 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018183 request1.traffic_annotation =
18184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018185 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418186 TestCompletionCallback callback1;
18187 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018188 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118189 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2418190
18191 // Now, start the second request and make sure it succeeds.
18192 HttpRequestInfo request2;
18193 request2.method = "GET";
18194 request2.url = GURL(https_url);
18195 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018196 request2.traffic_annotation =
18197 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018198 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418199 TestCompletionCallback callback2;
18200 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018201 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2418202
robpercival214763f2016-07-01 23:27:0118203 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2418204 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18205}
18206
bncd16676a2016-07-20 16:23:0118207TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0318208 ClientSocketPoolManager::set_max_sockets_per_group(
18209 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18210 ClientSocketPoolManager::set_max_sockets_per_pool(
18211 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18212
18213 // Use two different hosts with different IPs so they don't get pooled.
18214 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
18215 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0918216 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0318217
18218 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618219 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318220 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618221 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18224
Ryan Hamilton0239aac2018-05-19 00:03:1318225 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4918226 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318227 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118228 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0318229 };
Ryan Hamilton0239aac2018-05-19 00:03:1318230 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3518231 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318232 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4118233 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318234 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118235 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918236 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318237 };
18238
rdsmithebb50aa2015-11-12 03:44:3818239 // Use a separate test instance for the separate SpdySession that will be
18240 // created.
bncd16676a2016-07-20 16:23:0118241 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0118242 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1218243 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0318244
Ryan Hamilton0239aac2018-05-19 00:03:1318245 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4918246 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318247 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118248 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0318249 };
Ryan Hamilton0239aac2018-05-19 00:03:1318250 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3518251 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318252 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4118253 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318254 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118255 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918256 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318257 };
18258
Ryan Sleevib8d7ea02018-05-07 20:01:0118259 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1218260 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0318261
18262 MockWrite http_write[] = {
18263 MockWrite("GET / HTTP/1.1\r\n"
18264 "Host: www.a.com\r\n"
18265 "Connection: keep-alive\r\n\r\n"),
18266 };
18267
18268 MockRead http_read[] = {
18269 MockRead("HTTP/1.1 200 OK\r\n"),
18270 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18271 MockRead("Content-Length: 6\r\n\r\n"),
18272 MockRead("hello!"),
18273 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118274 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0318275 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18276
18277 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118278 SpdySessionKey spdy_session_key_a(
18279 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418280 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18281 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318282 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618283 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318284
18285 TestCompletionCallback callback;
18286 HttpRequestInfo request1;
18287 request1.method = "GET";
18288 request1.url = GURL("https://www.a.com/");
18289 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018290 request1.traffic_annotation =
18291 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818292 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918293 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318294
tfarina42834112016-09-22 13:38:2018295 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118296 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18297 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318298
18299 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218300 ASSERT_TRUE(response);
18301 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218302 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318303 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218304 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0318305
18306 std::string response_data;
robpercival214763f2016-07-01 23:27:0118307 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318308 EXPECT_EQ("hello!", response_data);
18309 trans.reset();
18310 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618311 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318312
18313 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118314 SpdySessionKey spdy_session_key_b(
18315 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418316 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18317 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318318 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618319 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318320 HttpRequestInfo request2;
18321 request2.method = "GET";
18322 request2.url = GURL("https://www.b.com/");
18323 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018324 request2.traffic_annotation =
18325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818326 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918327 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318328
tfarina42834112016-09-22 13:38:2018329 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18331 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318332
18333 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218334 ASSERT_TRUE(response);
18335 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218336 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318337 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218338 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118339 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318340 EXPECT_EQ("hello!", response_data);
18341 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618342 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318343 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618344 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318345
18346 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1118347 SpdySessionKey spdy_session_key_a1(
18348 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418349 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18350 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318351 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618352 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0318353 HttpRequestInfo request3;
18354 request3.method = "GET";
18355 request3.url = GURL("http://www.a.com/");
18356 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018357 request3.traffic_annotation =
18358 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818359 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918360 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318361
tfarina42834112016-09-22 13:38:2018362 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118363 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18364 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318365
18366 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218367 ASSERT_TRUE(response);
18368 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0318369 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
18370 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218371 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118372 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318373 EXPECT_EQ("hello!", response_data);
18374 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618375 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318376 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618377 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318378}
18379
bncd16676a2016-07-20 16:23:0118380TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418381 HttpRequestInfo request;
18382 request.method = "GET";
bncce36dca22015-04-21 22:11:2318383 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018384 request.traffic_annotation =
18385 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418386
danakj1fd259a02016-04-16 03:17:0918387 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618388 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418389
ttuttled9dbc652015-09-29 20:00:5918390 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418391 StaticSocketDataProvider data;
18392 data.set_connect_data(mock_connect);
18393 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_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418402
ttuttle1f2d7e92015-04-28 16:17:4718403 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618404 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718405 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118406 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918407
18408 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618409 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918410 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418411}
18412
bncd16676a2016-07-20 16:23:0118413TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418414 HttpRequestInfo request;
18415 request.method = "GET";
bncce36dca22015-04-21 22:11:2318416 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018417 request.traffic_annotation =
18418 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418419
danakj1fd259a02016-04-16 03:17:0918420 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618421 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418422
ttuttled9dbc652015-09-29 20:00:5918423 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418424 StaticSocketDataProvider data;
18425 data.set_connect_data(mock_connect);
18426 session_deps_.socket_factory->AddSocketDataProvider(&data);
18427
18428 TestCompletionCallback callback;
18429
tfarina42834112016-09-22 13:38:2018430 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418432
18433 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118434 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418435
ttuttle1f2d7e92015-04-28 16:17:4718436 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618437 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718438 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118439 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918440
18441 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618442 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918443 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418444}
18445
bncd16676a2016-07-20 16:23:0118446TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418447 HttpRequestInfo request;
18448 request.method = "GET";
bncce36dca22015-04-21 22:11:2318449 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018450 request.traffic_annotation =
18451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418452
danakj1fd259a02016-04-16 03:17:0918453 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618454 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418455
18456 MockWrite data_writes[] = {
18457 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18458 };
18459 MockRead data_reads[] = {
18460 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18461 };
18462
Ryan Sleevib8d7ea02018-05-07 20:01:0118463 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418464 session_deps_.socket_factory->AddSocketDataProvider(&data);
18465
18466 TestCompletionCallback callback;
18467
tfarina42834112016-09-22 13:38:2018468 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418470
18471 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118472 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418473}
18474
bncd16676a2016-07-20 16:23:0118475TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418476 HttpRequestInfo request;
18477 request.method = "GET";
bncce36dca22015-04-21 22:11:2318478 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018479 request.traffic_annotation =
18480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418481
danakj1fd259a02016-04-16 03:17:0918482 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618483 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418484
18485 MockWrite data_writes[] = {
18486 MockWrite(ASYNC, ERR_CONNECTION_RESET),
18487 };
18488 MockRead data_reads[] = {
18489 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18490 };
18491
Ryan Sleevib8d7ea02018-05-07 20:01:0118492 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418493 session_deps_.socket_factory->AddSocketDataProvider(&data);
18494
18495 TestCompletionCallback callback;
18496
tfarina42834112016-09-22 13:38:2018497 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118498 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418499
18500 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118501 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418502}
18503
bncd16676a2016-07-20 16:23:0118504TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418505 HttpRequestInfo request;
18506 request.method = "GET";
bncce36dca22015-04-21 22:11:2318507 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018508 request.traffic_annotation =
18509 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418510
danakj1fd259a02016-04-16 03:17:0918511 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618512 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418513
18514 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318515 MockWrite(
18516 "GET / HTTP/1.1\r\n"
18517 "Host: www.example.org\r\n"
18518 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418519 };
18520 MockRead data_reads[] = {
18521 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18522 };
18523
Ryan Sleevib8d7ea02018-05-07 20:01:0118524 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418525 session_deps_.socket_factory->AddSocketDataProvider(&data);
18526
18527 TestCompletionCallback callback;
18528
tfarina42834112016-09-22 13:38:2018529 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418531
18532 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118533 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418534}
18535
bncd16676a2016-07-20 16:23:0118536TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418537 HttpRequestInfo request;
18538 request.method = "GET";
bncce36dca22015-04-21 22:11:2318539 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018540 request.traffic_annotation =
18541 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418542
danakj1fd259a02016-04-16 03:17:0918543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418545
18546 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318547 MockWrite(
18548 "GET / HTTP/1.1\r\n"
18549 "Host: www.example.org\r\n"
18550 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418551 };
18552 MockRead data_reads[] = {
18553 MockRead(ASYNC, ERR_CONNECTION_RESET),
18554 };
18555
Ryan Sleevib8d7ea02018-05-07 20:01:0118556 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418557 session_deps_.socket_factory->AddSocketDataProvider(&data);
18558
18559 TestCompletionCallback callback;
18560
tfarina42834112016-09-22 13:38:2018561 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418563
18564 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118565 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418566}
18567
[email protected]043b68c82013-08-22 23:41:5218568// Tests that when a used socket is returned to the SSL socket pool, it's closed
18569// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118570TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218571 ClientSocketPoolManager::set_max_sockets_per_group(
18572 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18573 ClientSocketPoolManager::set_max_sockets_per_pool(
18574 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18575
18576 // Set up SSL request.
18577
18578 HttpRequestInfo ssl_request;
18579 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318580 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018581 ssl_request.traffic_annotation =
18582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218583
18584 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318585 MockWrite(
18586 "GET / HTTP/1.1\r\n"
18587 "Host: www.example.org\r\n"
18588 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218589 };
18590 MockRead ssl_reads[] = {
18591 MockRead("HTTP/1.1 200 OK\r\n"),
18592 MockRead("Content-Length: 11\r\n\r\n"),
18593 MockRead("hello world"),
18594 MockRead(SYNCHRONOUS, OK),
18595 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118596 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218597 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18598
18599 SSLSocketDataProvider ssl(ASYNC, OK);
18600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18601
18602 // Set up HTTP request.
18603
18604 HttpRequestInfo http_request;
18605 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318606 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018607 http_request.traffic_annotation =
18608 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218609
18610 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318611 MockWrite(
18612 "GET / HTTP/1.1\r\n"
18613 "Host: www.example.org\r\n"
18614 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218615 };
18616 MockRead http_reads[] = {
18617 MockRead("HTTP/1.1 200 OK\r\n"),
18618 MockRead("Content-Length: 7\r\n\r\n"),
18619 MockRead("falafel"),
18620 MockRead(SYNCHRONOUS, OK),
18621 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118622 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218623 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18624
danakj1fd259a02016-04-16 03:17:0918625 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218626
18627 // Start the SSL request.
18628 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618629 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018630 ASSERT_EQ(ERR_IO_PENDING,
18631 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18632 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218633
18634 // Start the HTTP request. Pool should stall.
18635 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618636 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018637 ASSERT_EQ(ERR_IO_PENDING,
18638 http_trans.Start(&http_request, http_callback.callback(),
18639 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118640 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218641
18642 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118643 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218644 std::string response_data;
bnc691fda62016-08-12 00:43:1618645 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218646 EXPECT_EQ("hello world", response_data);
18647
18648 // The SSL socket should automatically be closed, so the HTTP request can
18649 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318650 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118651 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218652
18653 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118654 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618655 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218656 EXPECT_EQ("falafel", response_data);
18657
dcheng48459ac22014-08-26 00:46:4118658 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218659}
18660
18661// Tests that when a SSL connection is established but there's no corresponding
18662// request that needs it, the new socket is closed if the transport socket pool
18663// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118664TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218665 ClientSocketPoolManager::set_max_sockets_per_group(
18666 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18667 ClientSocketPoolManager::set_max_sockets_per_pool(
18668 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18669
18670 // Set up an ssl request.
18671
18672 HttpRequestInfo ssl_request;
18673 ssl_request.method = "GET";
18674 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1018675 ssl_request.traffic_annotation =
18676 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218677
18678 // No data will be sent on the SSL socket.
18679 StaticSocketDataProvider ssl_data;
18680 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18681
18682 SSLSocketDataProvider ssl(ASYNC, OK);
18683 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18684
18685 // Set up HTTP request.
18686
18687 HttpRequestInfo http_request;
18688 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318689 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018690 http_request.traffic_annotation =
18691 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218692
18693 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318694 MockWrite(
18695 "GET / HTTP/1.1\r\n"
18696 "Host: www.example.org\r\n"
18697 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218698 };
18699 MockRead http_reads[] = {
18700 MockRead("HTTP/1.1 200 OK\r\n"),
18701 MockRead("Content-Length: 7\r\n\r\n"),
18702 MockRead("falafel"),
18703 MockRead(SYNCHRONOUS, OK),
18704 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118705 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218706 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18707
danakj1fd259a02016-04-16 03:17:0918708 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218709
18710 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18711 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918712 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918713 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318714 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218715
18716 // Start the HTTP request. Pool should stall.
18717 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618718 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018719 ASSERT_EQ(ERR_IO_PENDING,
18720 http_trans.Start(&http_request, http_callback.callback(),
18721 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118722 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218723
18724 // The SSL connection will automatically be closed once the connection is
18725 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118726 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218727 std::string response_data;
bnc691fda62016-08-12 00:43:1618728 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218729 EXPECT_EQ("falafel", response_data);
18730
dcheng48459ac22014-08-26 00:46:4118731 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218732}
18733
bncd16676a2016-07-20 16:23:0118734TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918735 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218736 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918737 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218738 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418739
18740 HttpRequestInfo request;
18741 request.method = "POST";
18742 request.url = GURL("http://www.foo.com/");
18743 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018744 request.traffic_annotation =
18745 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418746
danakj1fd259a02016-04-16 03:17:0918747 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618748 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418749 // Send headers successfully, but get an error while sending the body.
18750 MockWrite data_writes[] = {
18751 MockWrite("POST / HTTP/1.1\r\n"
18752 "Host: www.foo.com\r\n"
18753 "Connection: keep-alive\r\n"
18754 "Content-Length: 3\r\n\r\n"),
18755 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18756 };
18757
18758 MockRead data_reads[] = {
18759 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18760 MockRead("hello world"),
18761 MockRead(SYNCHRONOUS, OK),
18762 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118763 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418764 session_deps_.socket_factory->AddSocketDataProvider(&data);
18765
18766 TestCompletionCallback callback;
18767
tfarina42834112016-09-22 13:38:2018768 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118769 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418770
18771 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118772 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418773
bnc691fda62016-08-12 00:43:1618774 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218775 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418776
wezca1070932016-05-26 20:30:5218777 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418778 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18779
18780 std::string response_data;
bnc691fda62016-08-12 00:43:1618781 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118782 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418783 EXPECT_EQ("hello world", response_data);
18784}
18785
18786// This test makes sure the retry logic doesn't trigger when reading an error
18787// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118788TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418789 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918790 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418791 MockWrite data_writes[] = {
18792 MockWrite("GET / HTTP/1.1\r\n"
18793 "Host: www.foo.com\r\n"
18794 "Connection: keep-alive\r\n\r\n"),
18795 MockWrite("POST / HTTP/1.1\r\n"
18796 "Host: www.foo.com\r\n"
18797 "Connection: keep-alive\r\n"
18798 "Content-Length: 3\r\n\r\n"),
18799 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18800 };
18801
18802 MockRead data_reads[] = {
18803 MockRead("HTTP/1.1 200 Peachy\r\n"
18804 "Content-Length: 14\r\n\r\n"),
18805 MockRead("first response"),
18806 MockRead("HTTP/1.1 400 Not OK\r\n"
18807 "Content-Length: 15\r\n\r\n"),
18808 MockRead("second response"),
18809 MockRead(SYNCHRONOUS, OK),
18810 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118811 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418812 session_deps_.socket_factory->AddSocketDataProvider(&data);
18813
18814 TestCompletionCallback callback;
18815 HttpRequestInfo request1;
18816 request1.method = "GET";
18817 request1.url = GURL("http://www.foo.com/");
18818 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018819 request1.traffic_annotation =
18820 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418821
bnc87dcefc2017-05-25 12:47:5818822 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918823 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018824 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418826
18827 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118828 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418829
18830 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218831 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418832
wezca1070932016-05-26 20:30:5218833 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418834 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18835
18836 std::string response_data1;
18837 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118838 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418839 EXPECT_EQ("first response", response_data1);
18840 // Delete the transaction to release the socket back into the socket pool.
18841 trans1.reset();
18842
danakj1fd259a02016-04-16 03:17:0918843 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218844 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918845 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218846 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418847
18848 HttpRequestInfo request2;
18849 request2.method = "POST";
18850 request2.url = GURL("http://www.foo.com/");
18851 request2.upload_data_stream = &upload_data_stream;
18852 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018853 request2.traffic_annotation =
18854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418855
bnc691fda62016-08-12 00:43:1618856 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018857 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418859
18860 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118861 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418862
bnc691fda62016-08-12 00:43:1618863 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218864 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418865
wezca1070932016-05-26 20:30:5218866 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418867 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18868
18869 std::string response_data2;
bnc691fda62016-08-12 00:43:1618870 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118871 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418872 EXPECT_EQ("second response", response_data2);
18873}
18874
bncd16676a2016-07-20 16:23:0118875TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418876 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918877 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218878 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918879 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218880 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418881
18882 HttpRequestInfo request;
18883 request.method = "POST";
18884 request.url = GURL("http://www.foo.com/");
18885 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018886 request.traffic_annotation =
18887 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418888
danakj1fd259a02016-04-16 03:17:0918889 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618890 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418891 // Send headers successfully, but get an error while sending the body.
18892 MockWrite data_writes[] = {
18893 MockWrite("POST / HTTP/1.1\r\n"
18894 "Host: www.foo.com\r\n"
18895 "Connection: keep-alive\r\n"
18896 "Content-Length: 3\r\n\r\n"
18897 "fo"),
18898 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18899 };
18900
18901 MockRead data_reads[] = {
18902 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18903 MockRead("hello world"),
18904 MockRead(SYNCHRONOUS, OK),
18905 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118906 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418907 session_deps_.socket_factory->AddSocketDataProvider(&data);
18908
18909 TestCompletionCallback callback;
18910
tfarina42834112016-09-22 13:38:2018911 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418913
18914 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118915 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418916
bnc691fda62016-08-12 00:43:1618917 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218918 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418919
wezca1070932016-05-26 20:30:5218920 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418921 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18922
18923 std::string response_data;
bnc691fda62016-08-12 00:43:1618924 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118925 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418926 EXPECT_EQ("hello world", response_data);
18927}
18928
18929// This tests the more common case than the previous test, where headers and
18930// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118931TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718932 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418933
18934 HttpRequestInfo request;
18935 request.method = "POST";
18936 request.url = GURL("http://www.foo.com/");
18937 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018938 request.traffic_annotation =
18939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418940
danakj1fd259a02016-04-16 03:17:0918941 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618942 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418943 // Send headers successfully, but get an error while sending the body.
18944 MockWrite data_writes[] = {
18945 MockWrite("POST / HTTP/1.1\r\n"
18946 "Host: www.foo.com\r\n"
18947 "Connection: keep-alive\r\n"
18948 "Transfer-Encoding: chunked\r\n\r\n"),
18949 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18950 };
18951
18952 MockRead data_reads[] = {
18953 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18954 MockRead("hello world"),
18955 MockRead(SYNCHRONOUS, OK),
18956 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118957 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418958 session_deps_.socket_factory->AddSocketDataProvider(&data);
18959
18960 TestCompletionCallback callback;
18961
tfarina42834112016-09-22 13:38:2018962 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418964 // Make sure the headers are sent before adding a chunk. This ensures that
18965 // they can't be merged with the body in a single send. Not currently
18966 // necessary since a chunked body is never merged with headers, but this makes
18967 // the test more future proof.
18968 base::RunLoop().RunUntilIdle();
18969
mmenkecbc2b712014-10-09 20:29:0718970 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418971
18972 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118973 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418974
bnc691fda62016-08-12 00:43:1618975 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218976 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418977
wezca1070932016-05-26 20:30:5218978 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418979 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18980
18981 std::string response_data;
bnc691fda62016-08-12 00:43:1618982 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118983 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418984 EXPECT_EQ("hello world", response_data);
18985}
18986
bncd16676a2016-07-20 16:23:0118987TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918988 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218989 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918990 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218991 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418992
18993 HttpRequestInfo request;
18994 request.method = "POST";
18995 request.url = GURL("http://www.foo.com/");
18996 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018997 request.traffic_annotation =
18998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418999
danakj1fd259a02016-04-16 03:17:0919000 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619001 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419002
19003 MockWrite data_writes[] = {
19004 MockWrite("POST / HTTP/1.1\r\n"
19005 "Host: www.foo.com\r\n"
19006 "Connection: keep-alive\r\n"
19007 "Content-Length: 3\r\n\r\n"),
19008 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19009 };
19010
19011 MockRead data_reads[] = {
19012 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
19013 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
19014 MockRead("hello world"),
19015 MockRead(SYNCHRONOUS, OK),
19016 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119017 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419018 session_deps_.socket_factory->AddSocketDataProvider(&data);
19019
19020 TestCompletionCallback callback;
19021
tfarina42834112016-09-22 13:38:2019022 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119023 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419024
19025 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119026 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5419027
bnc691fda62016-08-12 00:43:1619028 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5219029 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5419030
wezca1070932016-05-26 20:30:5219031 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5419032 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
19033
19034 std::string response_data;
bnc691fda62016-08-12 00:43:1619035 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0119036 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5419037 EXPECT_EQ("hello world", response_data);
19038}
19039
bncd16676a2016-07-20 16:23:0119040TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0919041 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219042 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919043 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219044 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419045
19046 HttpRequestInfo request;
19047 request.method = "POST";
19048 request.url = GURL("http://www.foo.com/");
19049 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019050 request.traffic_annotation =
19051 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419052
danakj1fd259a02016-04-16 03:17:0919053 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619054 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419055 // Send headers successfully, but get an error while sending the body.
19056 MockWrite data_writes[] = {
19057 MockWrite("POST / HTTP/1.1\r\n"
19058 "Host: www.foo.com\r\n"
19059 "Connection: keep-alive\r\n"
19060 "Content-Length: 3\r\n\r\n"),
19061 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19062 };
19063
19064 MockRead data_reads[] = {
19065 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
19066 MockRead("hello world"),
19067 MockRead(SYNCHRONOUS, OK),
19068 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119069 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419070 session_deps_.socket_factory->AddSocketDataProvider(&data);
19071
19072 TestCompletionCallback callback;
19073
tfarina42834112016-09-22 13:38:2019074 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419076
19077 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119078 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419079}
19080
bncd16676a2016-07-20 16:23:0119081TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5419082 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0919083 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219084 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919085 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219086 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419087
19088 HttpRequestInfo request;
19089 request.method = "POST";
19090 request.url = GURL("http://www.foo.com/");
19091 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019092 request.traffic_annotation =
19093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419094
danakj1fd259a02016-04-16 03:17:0919095 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619096 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419097 // Send headers successfully, but get an error while sending the body.
19098 MockWrite data_writes[] = {
19099 MockWrite("POST / HTTP/1.1\r\n"
19100 "Host: www.foo.com\r\n"
19101 "Connection: keep-alive\r\n"
19102 "Content-Length: 3\r\n\r\n"),
19103 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19104 };
19105
19106 MockRead data_reads[] = {
19107 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
19108 MockRead("HTTP/1.0 302 Redirect\r\n"),
19109 MockRead("Location: http://somewhere-else.com/\r\n"),
19110 MockRead("Content-Length: 0\r\n\r\n"),
19111 MockRead(SYNCHRONOUS, OK),
19112 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119113 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419114 session_deps_.socket_factory->AddSocketDataProvider(&data);
19115
19116 TestCompletionCallback callback;
19117
tfarina42834112016-09-22 13:38:2019118 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419120
19121 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119122 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419123}
19124
bncd16676a2016-07-20 16:23:0119125TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0919126 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219127 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919128 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219129 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419130
19131 HttpRequestInfo request;
19132 request.method = "POST";
19133 request.url = GURL("http://www.foo.com/");
19134 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019135 request.traffic_annotation =
19136 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419137
danakj1fd259a02016-04-16 03:17:0919138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419140 // Send headers successfully, but get an error while sending the body.
19141 MockWrite data_writes[] = {
19142 MockWrite("POST / HTTP/1.1\r\n"
19143 "Host: www.foo.com\r\n"
19144 "Connection: keep-alive\r\n"
19145 "Content-Length: 3\r\n\r\n"),
19146 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19147 };
19148
19149 MockRead data_reads[] = {
19150 MockRead("HTTP 0.9 rocks!"),
19151 MockRead(SYNCHRONOUS, OK),
19152 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119153 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419154 session_deps_.socket_factory->AddSocketDataProvider(&data);
19155
19156 TestCompletionCallback callback;
19157
tfarina42834112016-09-22 13:38:2019158 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119159 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419160
19161 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119162 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419163}
19164
bncd16676a2016-07-20 16:23:0119165TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0919166 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219167 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919168 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219169 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419170
19171 HttpRequestInfo request;
19172 request.method = "POST";
19173 request.url = GURL("http://www.foo.com/");
19174 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019175 request.traffic_annotation =
19176 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419177
danakj1fd259a02016-04-16 03:17:0919178 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619179 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419180 // Send headers successfully, but get an error while sending the body.
19181 MockWrite data_writes[] = {
19182 MockWrite("POST / HTTP/1.1\r\n"
19183 "Host: www.foo.com\r\n"
19184 "Connection: keep-alive\r\n"
19185 "Content-Length: 3\r\n\r\n"),
19186 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19187 };
19188
19189 MockRead data_reads[] = {
19190 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
19191 MockRead(SYNCHRONOUS, OK),
19192 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119193 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419194 session_deps_.socket_factory->AddSocketDataProvider(&data);
19195
19196 TestCompletionCallback callback;
19197
tfarina42834112016-09-22 13:38:2019198 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119199 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419200
19201 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119202 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419203}
19204
Bence Békydca6bd92018-01-30 13:43:0619205#if BUILDFLAG(ENABLE_WEBSOCKETS)
19206
19207namespace {
19208
19209void AddWebSocketHeaders(HttpRequestHeaders* headers) {
19210 headers->SetHeader("Connection", "Upgrade");
19211 headers->SetHeader("Upgrade", "websocket");
19212 headers->SetHeader("Origin", "http://www.example.org");
19213 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0619214}
19215
19216} // namespace
19217
19218TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0119219 for (bool secure : {true, false}) {
19220 MockWrite data_writes[] = {
19221 MockWrite("GET / HTTP/1.1\r\n"
19222 "Host: www.example.org\r\n"
19223 "Connection: Upgrade\r\n"
19224 "Upgrade: websocket\r\n"
19225 "Origin: http://www.example.org\r\n"
19226 "Sec-WebSocket-Version: 13\r\n"
19227 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19228 "Sec-WebSocket-Extensions: permessage-deflate; "
19229 "client_max_window_bits\r\n\r\n")};
19230
19231 MockRead data_reads[] = {
19232 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19233 "Upgrade: websocket\r\n"
19234 "Connection: Upgrade\r\n"
19235 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
19236
Ryan Sleevib8d7ea02018-05-07 20:01:0119237 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0119238 session_deps_.socket_factory->AddSocketDataProvider(&data);
19239 SSLSocketDataProvider ssl(ASYNC, OK);
19240 if (secure)
19241 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0619242
19243 HttpRequestInfo request;
19244 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0119245 request.url =
19246 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19247 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1019248 request.traffic_annotation =
19249 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0619250
Bence Béky2fcf4fa2018-04-06 20:06:0119251 TestWebSocketHandshakeStreamCreateHelper
19252 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1519253
Bence Béky2fcf4fa2018-04-06 20:06:0119254 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0619255 HttpNetworkTransaction trans(LOW, session.get());
19256 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0119257 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0619258
19259 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0119260 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19261 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0619262
Bence Béky2fcf4fa2018-04-06 20:06:0119263 const HttpStreamRequest* stream_request = trans.stream_request_.get();
19264 ASSERT_TRUE(stream_request);
19265 EXPECT_EQ(&websocket_handshake_stream_create_helper,
19266 stream_request->websocket_handshake_stream_create_helper());
19267
19268 rv = callback.WaitForResult();
19269 EXPECT_THAT(rv, IsOk());
19270
19271 EXPECT_TRUE(data.AllReadDataConsumed());
19272 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0619273 }
19274}
19275
Adam Rice425cf122015-01-19 06:18:2419276// Verify that proxy headers are not sent to the destination server when
19277// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0119278TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2419279 HttpRequestInfo request;
19280 request.method = "GET";
bncce36dca22015-04-21 22:11:2319281 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019282 request.traffic_annotation =
19283 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419284 AddWebSocketHeaders(&request.extra_headers);
19285
19286 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919287 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619288 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919289 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419290
danakj1fd259a02016-04-16 03:17:0919291 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419292
19293 // Since a proxy is configured, try to establish a tunnel.
19294 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1719295 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19296 "Host: www.example.org:443\r\n"
19297 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419298
19299 // After calling trans->RestartWithAuth(), this is the request we should
19300 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1719301 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19302 "Host: www.example.org:443\r\n"
19303 "Proxy-Connection: keep-alive\r\n"
19304 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419305
rsleevidb16bb02015-11-12 23:47:1719306 MockWrite("GET / HTTP/1.1\r\n"
19307 "Host: www.example.org\r\n"
19308 "Connection: Upgrade\r\n"
19309 "Upgrade: websocket\r\n"
19310 "Origin: http://www.example.org\r\n"
19311 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1519312 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19313 "Sec-WebSocket-Extensions: permessage-deflate; "
19314 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419315
19316 // The proxy responds to the connect with a 407, using a persistent
19317 // connection.
19318 MockRead data_reads[] = {
19319 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1519320 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
19321 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
19322 "Content-Length: 0\r\n"
19323 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419324
19325 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19326
Bence Béky8d1c6052018-02-07 12:48:1519327 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19328 "Upgrade: websocket\r\n"
19329 "Connection: Upgrade\r\n"
19330 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419331
Ryan Sleevib8d7ea02018-05-07 20:01:0119332 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419333 session_deps_.socket_factory->AddSocketDataProvider(&data);
19334 SSLSocketDataProvider ssl(ASYNC, OK);
19335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19336
Bence Béky8d1c6052018-02-07 12:48:1519337 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19338
bnc87dcefc2017-05-25 12:47:5819339 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919340 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419341 trans->SetWebSocketHandshakeStreamCreateHelper(
19342 &websocket_stream_create_helper);
19343
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
19354 const HttpResponseInfo* response = trans->GetResponseInfo();
19355 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219356 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419357 EXPECT_EQ(407, response->headers->response_code());
19358
19359 {
19360 TestCompletionCallback callback;
19361
19362 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
19363 callback.callback());
robpercival214763f2016-07-01 23:27:0119364 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419365
19366 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119367 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419368 }
19369
19370 response = trans->GetResponseInfo();
19371 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219372 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419373
19374 EXPECT_EQ(101, response->headers->response_code());
19375
19376 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119377 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419378}
19379
19380// Verify that proxy headers are not sent to the destination server when
19381// establishing a tunnel for an insecure WebSocket connection.
19382// This requires the authentication info to be injected into the auth cache
19383// due to crbug.com/395064
19384// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0119385TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2419386 HttpRequestInfo request;
19387 request.method = "GET";
bncce36dca22015-04-21 22:11:2319388 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019389 request.traffic_annotation =
19390 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419391 AddWebSocketHeaders(&request.extra_headers);
19392
19393 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919394 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619395 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919396 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419397
danakj1fd259a02016-04-16 03:17:0919398 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419399
19400 MockWrite data_writes[] = {
19401 // Try to establish a tunnel for the WebSocket connection, with
19402 // credentials. Because WebSockets have a separate set of socket pools,
19403 // they cannot and will not use the same TCP/IP connection as the
19404 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1519405 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
19406 "Host: www.example.org:80\r\n"
19407 "Proxy-Connection: keep-alive\r\n"
19408 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419409
Bence Béky8d1c6052018-02-07 12:48:1519410 MockWrite("GET / HTTP/1.1\r\n"
19411 "Host: www.example.org\r\n"
19412 "Connection: Upgrade\r\n"
19413 "Upgrade: websocket\r\n"
19414 "Origin: http://www.example.org\r\n"
19415 "Sec-WebSocket-Version: 13\r\n"
19416 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19417 "Sec-WebSocket-Extensions: permessage-deflate; "
19418 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419419
19420 MockRead data_reads[] = {
19421 // HTTP CONNECT with credentials.
19422 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19423
19424 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1519425 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19426 "Upgrade: websocket\r\n"
19427 "Connection: Upgrade\r\n"
19428 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419429
Ryan Sleevib8d7ea02018-05-07 20:01:0119430 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419431 session_deps_.socket_factory->AddSocketDataProvider(&data);
19432
19433 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3319434 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2619435 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
19436 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2419437
Bence Béky8d1c6052018-02-07 12:48:1519438 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19439
bnc87dcefc2017-05-25 12:47:5819440 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919441 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419442 trans->SetWebSocketHandshakeStreamCreateHelper(
19443 &websocket_stream_create_helper);
19444
19445 TestCompletionCallback callback;
19446
tfarina42834112016-09-22 13:38:2019447 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119448 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419449
19450 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119451 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419452
19453 const HttpResponseInfo* response = trans->GetResponseInfo();
19454 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219455 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419456
19457 EXPECT_EQ(101, response->headers->response_code());
19458
19459 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119460 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419461}
19462
Matt Menke1d6093e32019-03-22 17:33:4319463// WebSockets over QUIC is not supported, including over QUIC proxies.
19464TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
19465 for (bool secure : {true, false}) {
19466 SCOPED_TRACE(secure);
19467 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619468 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke1d6093e32019-03-22 17:33:4319469 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
19470 session_deps_.enable_quic = true;
19471
19472 HttpRequestInfo request;
19473 request.url =
19474 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19475 AddWebSocketHeaders(&request.extra_headers);
19476 request.traffic_annotation =
19477 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19478
19479 TestWebSocketHandshakeStreamCreateHelper
19480 websocket_handshake_stream_create_helper;
19481
19482 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19483 HttpNetworkTransaction trans(LOW, session.get());
19484 trans.SetWebSocketHandshakeStreamCreateHelper(
19485 &websocket_handshake_stream_create_helper);
19486
19487 TestCompletionCallback callback;
19488 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19489 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19490
19491 rv = callback.WaitForResult();
19492 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
19493 }
19494}
19495
Bence Békydca6bd92018-01-30 13:43:0619496#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
19497
bncd16676a2016-07-20 16:23:0119498TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0919499 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219500 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919501 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219502 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219503
19504 HttpRequestInfo request;
19505 request.method = "POST";
19506 request.url = GURL("http://www.foo.com/");
19507 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019508 request.traffic_annotation =
19509 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219510
danakj1fd259a02016-04-16 03:17:0919511 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619512 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219513 MockWrite data_writes[] = {
19514 MockWrite("POST / HTTP/1.1\r\n"
19515 "Host: www.foo.com\r\n"
19516 "Connection: keep-alive\r\n"
19517 "Content-Length: 3\r\n\r\n"),
19518 MockWrite("foo"),
19519 };
19520
19521 MockRead data_reads[] = {
19522 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19523 MockRead(SYNCHRONOUS, OK),
19524 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119525 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219526 session_deps_.socket_factory->AddSocketDataProvider(&data);
19527
19528 TestCompletionCallback callback;
19529
19530 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019531 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119532 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219533
19534 std::string response_data;
bnc691fda62016-08-12 00:43:1619535 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219536
Ryan Sleevib8d7ea02018-05-07 20:01:0119537 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19538 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219539}
19540
bncd16676a2016-07-20 16:23:0119541TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919542 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219543 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919544 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219545 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219546
19547 HttpRequestInfo request;
19548 request.method = "POST";
19549 request.url = GURL("http://www.foo.com/");
19550 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019551 request.traffic_annotation =
19552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219553
danakj1fd259a02016-04-16 03:17:0919554 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619555 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219556 MockWrite data_writes[] = {
19557 MockWrite("POST / HTTP/1.1\r\n"
19558 "Host: www.foo.com\r\n"
19559 "Connection: keep-alive\r\n"
19560 "Content-Length: 3\r\n\r\n"),
19561 MockWrite("foo"),
19562 };
19563
19564 MockRead data_reads[] = {
19565 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19566 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19567 MockRead(SYNCHRONOUS, OK),
19568 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119569 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219570 session_deps_.socket_factory->AddSocketDataProvider(&data);
19571
19572 TestCompletionCallback callback;
19573
19574 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019575 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119576 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219577
19578 std::string response_data;
bnc691fda62016-08-12 00:43:1619579 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219580
Ryan Sleevib8d7ea02018-05-07 20:01:0119581 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19582 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219583}
19584
bncd16676a2016-07-20 16:23:0119585TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219586 ChunkedUploadDataStream upload_data_stream(0);
19587
19588 HttpRequestInfo request;
19589 request.method = "POST";
19590 request.url = GURL("http://www.foo.com/");
19591 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019592 request.traffic_annotation =
19593 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219594
danakj1fd259a02016-04-16 03:17:0919595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619596 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219597 // Send headers successfully, but get an error while sending the body.
19598 MockWrite data_writes[] = {
19599 MockWrite("POST / HTTP/1.1\r\n"
19600 "Host: www.foo.com\r\n"
19601 "Connection: keep-alive\r\n"
19602 "Transfer-Encoding: chunked\r\n\r\n"),
19603 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19604 };
19605
19606 MockRead data_reads[] = {
19607 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19608 MockRead(SYNCHRONOUS, OK),
19609 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119610 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219611 session_deps_.socket_factory->AddSocketDataProvider(&data);
19612
19613 TestCompletionCallback callback;
19614
19615 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019616 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219617
19618 base::RunLoop().RunUntilIdle();
19619 upload_data_stream.AppendData("f", 1, false);
19620
19621 base::RunLoop().RunUntilIdle();
19622 upload_data_stream.AppendData("oo", 2, true);
19623
robpercival214763f2016-07-01 23:27:0119624 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219625
19626 std::string response_data;
bnc691fda62016-08-12 00:43:1619627 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219628
Ryan Sleevib8d7ea02018-05-07 20:01:0119629 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19630 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219631}
19632
eustasc7d27da2017-04-06 10:33:2019633void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19634 const std::string& accept_encoding,
19635 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319636 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019637 bool should_match) {
19638 HttpRequestInfo request;
19639 request.method = "GET";
19640 request.url = GURL("http://www.foo.com/");
19641 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19642 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1019643 request.traffic_annotation =
19644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019645
19646 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19647 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19648 // Send headers successfully, but get an error while sending the body.
19649 MockWrite data_writes[] = {
19650 MockWrite("GET / HTTP/1.1\r\n"
19651 "Host: www.foo.com\r\n"
19652 "Connection: keep-alive\r\n"
19653 "Accept-Encoding: "),
19654 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19655 };
19656
sky50576f32017-05-01 19:28:0319657 std::string response_code = "200 OK";
19658 std::string extra;
19659 if (!location.empty()) {
19660 response_code = "301 Redirect\r\nLocation: ";
19661 response_code.append(location);
19662 }
19663
eustasc7d27da2017-04-06 10:33:2019664 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319665 MockRead("HTTP/1.0 "),
19666 MockRead(response_code.data()),
19667 MockRead("\r\nContent-Encoding: "),
19668 MockRead(content_encoding.data()),
19669 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019670 MockRead(SYNCHRONOUS, OK),
19671 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119672 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019673 session_deps->socket_factory->AddSocketDataProvider(&data);
19674
19675 TestCompletionCallback callback;
19676
19677 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19679
19680 rv = callback.WaitForResult();
19681 if (should_match) {
19682 EXPECT_THAT(rv, IsOk());
19683 } else {
19684 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19685 }
19686}
19687
19688TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319689 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019690}
19691
19692TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319693 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19694 true);
eustasc7d27da2017-04-06 10:33:2019695}
19696
19697TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19698 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319699 "", false);
19700}
19701
19702TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19703 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19704 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019705}
19706
xunjieli96f2a402017-06-05 17:24:2719707TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19708 ProxyConfig proxy_config;
19709 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19710 proxy_config.set_pac_mandatory(true);
19711 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619712 session_deps_.proxy_resolution_service.reset(
19713 new ConfiguredProxyResolutionService(
19714 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19715 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919716 std::make_unique<FailingProxyResolverFactory>(), nullptr,
19717 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719718
19719 HttpRequestInfo request;
19720 request.method = "GET";
19721 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019722 request.traffic_annotation =
19723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719724
19725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19726 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19727
19728 TestCompletionCallback callback;
19729
19730 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19732 EXPECT_THAT(callback.WaitForResult(),
19733 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19734}
19735
19736TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19737 ProxyConfig proxy_config;
19738 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19739 proxy_config.set_pac_mandatory(true);
19740 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19741 new MockAsyncProxyResolverFactory(false);
19742 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619743 session_deps_.proxy_resolution_service.reset(
19744 new ConfiguredProxyResolutionService(
19745 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19746 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919747 base::WrapUnique(proxy_resolver_factory), nullptr,
19748 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719749 HttpRequestInfo request;
19750 request.method = "GET";
19751 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019752 request.traffic_annotation =
19753 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719754
19755 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19756 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19757
19758 TestCompletionCallback callback;
19759 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19761
19762 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19763 ERR_FAILED, &resolver);
19764 EXPECT_THAT(callback.WaitForResult(),
19765 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19766}
19767
19768TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919769 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619770 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919771 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719772 session_deps_.enable_quic = false;
19773 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19774
19775 HttpRequestInfo request;
19776 request.method = "GET";
19777 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019778 request.traffic_annotation =
19779 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719780
19781 TestCompletionCallback callback;
19782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19783 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19784 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19785
19786 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19787}
19788
Douglas Creager3cb042052018-11-06 23:08:5219789//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419790// Reporting tests
19791
19792#if BUILDFLAG(ENABLE_REPORTING)
19793class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19794 protected:
Matt Menkef437a87e2020-10-22 23:22:2419795 HttpNetworkTransactionReportingTest() {
19796 feature_list_.InitAndEnableFeature(
19797 features::kPartitionNelAndReportingByNetworkIsolationKey);
19798 }
19799
Douglas Creager134b52e2018-11-09 18:00:1419800 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619801 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419802 auto test_reporting_context = std::make_unique<TestReportingContext>(
19803 &clock_, &tick_clock_, ReportingPolicy());
19804 test_reporting_context_ = test_reporting_context.get();
19805 session_deps_.reporting_service =
19806 ReportingService::CreateForTesting(std::move(test_reporting_context));
19807 }
19808
19809 TestReportingContext* reporting_context() const {
19810 return test_reporting_context_;
19811 }
19812
19813 void clear_reporting_service() {
19814 session_deps_.reporting_service.reset();
19815 test_reporting_context_ = nullptr;
19816 }
19817
19818 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219819 void RequestPolicy(CertStatus cert_status = 0) {
19820 HttpRequestInfo request;
19821 request.method = "GET";
19822 request.url = GURL(url_);
19823 request.traffic_annotation =
19824 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkef437a87e2020-10-22 23:22:2419825 request.network_isolation_key = kNetworkIsolationKey;
Lily Chenfec60d92019-01-24 01:16:4219826
Lily Chend3930e72019-03-01 19:31:1119827 MockWrite data_writes[] = {
19828 MockWrite("GET / HTTP/1.1\r\n"
19829 "Host: www.example.org\r\n"
19830 "Connection: keep-alive\r\n\r\n"),
19831 };
Douglas Creager134b52e2018-11-09 18:00:1419832 MockRead data_reads[] = {
19833 MockRead("HTTP/1.0 200 OK\r\n"),
19834 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19835 "\"endpoints\": [{\"url\": "
19836 "\"https://www.example.org/upload/\"}]}\r\n"),
19837 MockRead("\r\n"),
19838 MockRead("hello world"),
19839 MockRead(SYNCHRONOUS, OK),
19840 };
Douglas Creager134b52e2018-11-09 18:00:1419841
Lily Chenfec60d92019-01-24 01:16:4219842 StaticSocketDataProvider reads(data_reads, data_writes);
19843 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419844
19845 SSLSocketDataProvider ssl(ASYNC, OK);
19846 if (request.url.SchemeIsCryptographic()) {
19847 ssl.ssl_info.cert =
19848 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19849 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219850 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19852 }
19853
Douglas Creager134b52e2018-11-09 18:00:1419854 TestCompletionCallback callback;
19855 auto session = CreateSession(&session_deps_);
19856 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19857 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219858 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419859 }
19860
19861 protected:
19862 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419863
19864 private:
Matt Menkef437a87e2020-10-22 23:22:2419865 base::test::ScopedFeatureList feature_list_;
Douglas Creager134b52e2018-11-09 18:00:1419866 TestReportingContext* test_reporting_context_;
19867};
19868
19869TEST_F(HttpNetworkTransactionReportingTest,
19870 DontProcessReportToHeaderNoService) {
Douglas Creager134b52e2018-11-09 18:00:1419871 clear_reporting_service();
19872 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219873 // No crash.
Douglas Creager134b52e2018-11-09 18:00:1419874}
19875
19876TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
Douglas Creager134b52e2018-11-09 18:00:1419877 url_ = "http://www.example.org/";
19878 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219879 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419880}
19881
19882TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19883 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419884 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019885 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419886 reporting_context()->cache()->GetEndpointForTesting(
Lily Chenad5dd0802020-03-10 21:58:0919887 ReportingEndpointGroupKey(
Matt Menkef437a87e2020-10-22 23:22:2419888 kNetworkIsolationKey,
Lily Chenad5dd0802020-03-10 21:58:0919889 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
Lily Chenefb6fcf2019-04-19 04:17:5419890 GURL("https://www.example.org/upload/"));
19891 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419892}
19893
19894TEST_F(HttpNetworkTransactionReportingTest,
19895 DontProcessReportToHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4219896 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19897 RequestPolicy(cert_status);
Lily Chen9364a4c2020-06-25 16:07:5219898 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419899}
19900#endif // BUILDFLAG(ENABLE_REPORTING)
19901
19902//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219903// Network Error Logging tests
19904
19905#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219906namespace {
19907
19908const char kUserAgent[] = "Mozilla/1.0";
19909const char kReferrer[] = "https://www.referrer.org/";
19910
19911} // namespace
19912
Douglas Creager3cb042052018-11-06 23:08:5219913class HttpNetworkTransactionNetworkErrorLoggingTest
19914 : public HttpNetworkTransactionTest {
19915 protected:
19916 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619917 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219918 auto network_error_logging_service =
19919 std::make_unique<TestNetworkErrorLoggingService>();
19920 test_network_error_logging_service_ = network_error_logging_service.get();
19921 session_deps_.network_error_logging_service =
19922 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219923
19924 extra_headers_.SetHeader("User-Agent", kUserAgent);
19925 extra_headers_.SetHeader("Referer", kReferrer);
19926
19927 request_.method = "GET";
19928 request_.url = GURL(url_);
Matt Menkef437a87e2020-10-22 23:22:2419929 request_.network_isolation_key = kNetworkIsolationKey;
Lily Chenfec60d92019-01-24 01:16:4219930 request_.extra_headers = extra_headers_;
19931 request_.reporting_upload_depth = reporting_upload_depth_;
19932 request_.traffic_annotation =
19933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219934 }
19935
19936 TestNetworkErrorLoggingService* network_error_logging_service() const {
19937 return test_network_error_logging_service_;
19938 }
19939
19940 void clear_network_error_logging_service() {
19941 session_deps_.network_error_logging_service.reset();
19942 test_network_error_logging_service_ = nullptr;
19943 }
19944
19945 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219946 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619947 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319948 MockWrite data_writes[] = {
19949 MockWrite("GET / HTTP/1.1\r\n"
19950 "Host: www.example.org\r\n"
19951 "Connection: keep-alive\r\n"),
19952 MockWrite(ASYNC, extra_header_string.data(),
19953 extra_header_string.size()),
19954 };
Lily Chend3930e72019-03-01 19:31:1119955 MockRead data_reads[] = {
19956 MockRead("HTTP/1.0 200 OK\r\n"),
19957 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19958 MockRead("\r\n"),
19959 MockRead("hello world"),
19960 MockRead(SYNCHRONOUS, OK),
19961 };
Douglas Creager3cb042052018-11-06 23:08:5219962
Lily Chenfec60d92019-01-24 01:16:4219963 StaticSocketDataProvider reads(data_reads, data_writes);
19964 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219965
19966 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219967 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219968 ssl.ssl_info.cert =
19969 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19970 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219971 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219972 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19973 }
19974
Douglas Creager3cb042052018-11-06 23:08:5219975 TestCompletionCallback callback;
19976 auto session = CreateSession(&session_deps_);
19977 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219978 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19979 EXPECT_THAT(callback.GetResult(rv), IsOk());
19980
19981 std::string response_data;
19982 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19983 EXPECT_EQ("hello world", response_data);
19984 }
19985
19986 void CheckReport(size_t index,
19987 int status_code,
19988 int error_type,
19989 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19990 ASSERT_LT(index, network_error_logging_service()->errors().size());
19991
19992 const NetworkErrorLoggingService::RequestDetails& error =
19993 network_error_logging_service()->errors()[index];
19994 EXPECT_EQ(url_, error.uri);
Matt Menkef437a87e2020-10-22 23:22:2419995 EXPECT_EQ(kNetworkIsolationKey, error.network_isolation_key);
Lily Chenfec60d92019-01-24 01:16:4219996 EXPECT_EQ(kReferrer, error.referrer);
19997 EXPECT_EQ(kUserAgent, error.user_agent);
19998 EXPECT_EQ(server_ip, error.server_ip);
19999 EXPECT_EQ("http/1.1", error.protocol);
20000 EXPECT_EQ("GET", error.method);
20001 EXPECT_EQ(status_code, error.status_code);
20002 EXPECT_EQ(error_type, error.type);
20003 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5220004 }
20005
20006 protected:
20007 std::string url_ = "https://www.example.org/";
20008 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4220009 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3620010 HttpRequestHeaders extra_headers_;
20011 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5220012
20013 private:
20014 TestNetworkErrorLoggingService* test_network_error_logging_service_;
20015};
20016
20017TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20018 DontProcessNelHeaderNoService) {
Douglas Creager3cb042052018-11-06 23:08:5220019 clear_network_error_logging_service();
20020 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4920021 // No crash.
Douglas Creager3cb042052018-11-06 23:08:5220022}
20023
20024TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20025 DontProcessNelHeaderHttp) {
Douglas Creager3cb042052018-11-06 23:08:5220026 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4220027 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5220028 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4920029 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5220030}
20031
Lily Chen90ae93cc2019-02-14 01:15:3920032// Don't set NEL policies received on a proxied connection.
20033TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20034 DontProcessNelHeaderProxy) {
20035 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620036 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920037 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1420038 RecordingBoundTestNetLog log;
Lily Chen90ae93cc2019-02-14 01:15:3920039 session_deps_.net_log = log.bound().net_log();
20040 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20041
20042 HttpRequestInfo request;
20043 request.method = "GET";
20044 request.url = GURL("https://www.example.org/");
20045 request.traffic_annotation =
20046 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20047
20048 // Since we have proxy, should try to establish tunnel.
20049 MockWrite data_writes1[] = {
20050 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20051 "Host: www.example.org:443\r\n"
20052 "Proxy-Connection: keep-alive\r\n\r\n"),
20053
20054 MockWrite("GET / HTTP/1.1\r\n"
20055 "Host: www.example.org\r\n"
20056 "Connection: keep-alive\r\n\r\n"),
20057 };
20058
20059 MockRead data_reads1[] = {
20060 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20061
20062 MockRead("HTTP/1.1 200 OK\r\n"),
20063 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
20064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20065 MockRead("Content-Length: 100\r\n\r\n"),
20066 MockRead(SYNCHRONOUS, OK),
20067 };
20068
20069 StaticSocketDataProvider data1(data_reads1, data_writes1);
20070 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20071 SSLSocketDataProvider ssl(ASYNC, OK);
20072 ssl.ssl_info.cert =
20073 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
20074 ASSERT_TRUE(ssl.ssl_info.cert);
20075 ssl.ssl_info.cert_status = 0;
20076 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20077
20078 TestCompletionCallback callback1;
20079 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20080
20081 int rv = trans.Start(&request, callback1.callback(), log.bound());
20082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20083
20084 rv = callback1.WaitForResult();
20085 EXPECT_THAT(rv, IsOk());
20086
20087 const HttpResponseInfo* response = trans.GetResponseInfo();
20088 ASSERT_TRUE(response);
20089 EXPECT_EQ(200, response->headers->response_code());
20090 EXPECT_TRUE(response->was_fetched_via_proxy);
20091
20092 // No NEL header was set.
20093 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
20094}
20095
Douglas Creager3cb042052018-11-06 23:08:5220096TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
20097 RequestPolicy();
20098 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
20099 const auto& header = network_error_logging_service()->headers()[0];
Matt Menkef437a87e2020-10-22 23:22:2420100 EXPECT_EQ(kNetworkIsolationKey, header.network_isolation_key);
Douglas Creager3cb042052018-11-06 23:08:5220101 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
20102 header.origin);
20103 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
20104 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
20105}
20106
20107TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20108 DontProcessNelHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4220109 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
20110 RequestPolicy(cert_status);
Lily Chena9e9d6cb2020-06-25 17:34:4920111 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5220112}
Douglas Creageref5eecdc2018-11-09 20:50:3620113
Lily Chenfec60d92019-01-24 01:16:4220114TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3620115 RequestPolicy();
20116 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220117 CheckReport(0 /* index */, 200 /* status_code */, OK);
20118}
20119
20120TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20121 CreateReportErrorAfterStart) {
20122 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20123 auto trans =
20124 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20125
20126 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
20127 StaticSocketDataProvider data;
20128 data.set_connect_data(mock_connect);
20129 session_deps_.socket_factory->AddSocketDataProvider(&data);
20130
20131 TestCompletionCallback callback;
20132
20133 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20134 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20135
20136 trans.reset();
20137
20138 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20139 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20140 IPAddress() /* server_ip */);
20141}
20142
20143// Same as above except the error is ASYNC
20144TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20145 CreateReportErrorAfterStartAsync) {
20146 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20147 auto trans =
20148 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20149
20150 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
20151 StaticSocketDataProvider data;
20152 data.set_connect_data(mock_connect);
20153 session_deps_.socket_factory->AddSocketDataProvider(&data);
20154
20155 TestCompletionCallback callback;
20156
20157 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20158 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20159
20160 trans.reset();
20161
20162 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20163 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20164 IPAddress() /* server_ip */);
20165}
20166
20167TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20168 CreateReportReadBodyError) {
20169 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320170 MockWrite data_writes[] = {
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 };
Lily Chend3930e72019-03-01 19:31:1120176 MockRead data_reads[] = {
20177 MockRead("HTTP/1.0 200 OK\r\n"),
20178 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20179 MockRead("hello world"),
20180 MockRead(SYNCHRONOUS, OK),
20181 };
Lily Chenfec60d92019-01-24 01:16:4220182
20183 StaticSocketDataProvider reads(data_reads, data_writes);
20184 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20185
20186 SSLSocketDataProvider ssl(ASYNC, OK);
20187 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20188
20189 // Log start time
20190 base::TimeTicks start_time = base::TimeTicks::Now();
20191
20192 TestCompletionCallback callback;
20193 auto session = CreateSession(&session_deps_);
20194 auto trans =
20195 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20196 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20197 EXPECT_THAT(callback.GetResult(rv), IsOk());
20198
20199 const HttpResponseInfo* response = trans->GetResponseInfo();
20200 ASSERT_TRUE(response);
20201
20202 EXPECT_TRUE(response->headers);
20203 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20204
20205 std::string response_data;
20206 rv = ReadTransaction(trans.get(), &response_data);
20207 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20208
20209 trans.reset();
20210
20211 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20212
20213 CheckReport(0 /* index */, 200 /* status_code */,
20214 ERR_CONTENT_LENGTH_MISMATCH);
20215 const NetworkErrorLoggingService::RequestDetails& error =
20216 network_error_logging_service()->errors()[0];
20217 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20218}
20219
20220// Same as above except the final read is ASYNC.
20221TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20222 CreateReportReadBodyErrorAsync) {
20223 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320224 MockWrite data_writes[] = {
20225 MockWrite("GET / HTTP/1.1\r\n"
20226 "Host: www.example.org\r\n"
20227 "Connection: keep-alive\r\n"),
20228 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20229 };
Lily Chend3930e72019-03-01 19:31:1120230 MockRead data_reads[] = {
20231 MockRead("HTTP/1.0 200 OK\r\n"),
20232 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20233 MockRead("hello world"),
20234 MockRead(ASYNC, OK),
20235 };
Lily Chenfec60d92019-01-24 01:16:4220236
20237 StaticSocketDataProvider reads(data_reads, data_writes);
20238 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20239
20240 SSLSocketDataProvider ssl(ASYNC, OK);
20241 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20242
20243 // Log start time
20244 base::TimeTicks start_time = base::TimeTicks::Now();
20245
20246 TestCompletionCallback callback;
20247 auto session = CreateSession(&session_deps_);
20248 auto trans =
20249 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20250 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20251 EXPECT_THAT(callback.GetResult(rv), IsOk());
20252
20253 const HttpResponseInfo* response = trans->GetResponseInfo();
20254 ASSERT_TRUE(response);
20255
20256 EXPECT_TRUE(response->headers);
20257 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20258
20259 std::string response_data;
20260 rv = ReadTransaction(trans.get(), &response_data);
20261 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20262
20263 trans.reset();
20264
20265 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20266
20267 CheckReport(0 /* index */, 200 /* status_code */,
20268 ERR_CONTENT_LENGTH_MISMATCH);
20269 const NetworkErrorLoggingService::RequestDetails& error =
20270 network_error_logging_service()->errors()[0];
20271 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20272}
20273
20274TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20275 CreateReportRestartWithAuth) {
20276 std::string extra_header_string = extra_headers_.ToString();
20277 static const base::TimeDelta kSleepDuration =
20278 base::TimeDelta::FromMilliseconds(10);
20279
20280 MockWrite data_writes1[] = {
20281 MockWrite("GET / HTTP/1.1\r\n"
20282 "Host: www.example.org\r\n"
20283 "Connection: keep-alive\r\n"),
20284 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20285 };
20286
20287 MockRead data_reads1[] = {
20288 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20289 // Give a couple authenticate options (only the middle one is actually
20290 // supported).
20291 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20292 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20293 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20294 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20295 // Large content-length -- won't matter, as connection will be reset.
20296 MockRead("Content-Length: 10000\r\n\r\n"),
20297 MockRead(SYNCHRONOUS, ERR_FAILED),
20298 };
20299
20300 // After calling trans->RestartWithAuth(), this is the request we should
20301 // be issuing -- the final header line contains the credentials.
20302 MockWrite data_writes2[] = {
20303 MockWrite("GET / HTTP/1.1\r\n"
20304 "Host: www.example.org\r\n"
20305 "Connection: keep-alive\r\n"
20306 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20307 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20308 };
20309
20310 // Lastly, the server responds with the actual content.
20311 MockRead data_reads2[] = {
20312 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20313 MockRead("hello world"),
20314 MockRead(SYNCHRONOUS, OK),
20315 };
20316
20317 StaticSocketDataProvider data1(data_reads1, data_writes1);
20318 StaticSocketDataProvider data2(data_reads2, data_writes2);
20319 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20320 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20321
20322 SSLSocketDataProvider ssl1(ASYNC, OK);
20323 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20324 SSLSocketDataProvider ssl2(ASYNC, OK);
20325 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20326
20327 base::TimeTicks start_time = base::TimeTicks::Now();
20328 base::TimeTicks restart_time;
20329
20330 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20331 auto trans =
20332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20333
20334 TestCompletionCallback callback1;
20335
20336 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20337 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20338
20339 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20340
20341 TestCompletionCallback callback2;
20342
20343 // Wait 10 ms then restart with auth
20344 FastForwardBy(kSleepDuration);
20345 restart_time = base::TimeTicks::Now();
20346 rv =
20347 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20348 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20349
20350 std::string response_data;
20351 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20352 EXPECT_EQ("hello world", response_data);
20353
20354 trans.reset();
20355
20356 // One 401 report for the auth challenge, then a 200 report for the successful
20357 // retry. Note that we don't report the error draining the body, as the first
20358 // request already generated a report for the auth challenge.
20359 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20360
20361 // Check error report contents
20362 CheckReport(0 /* index */, 401 /* status_code */, OK);
20363 CheckReport(1 /* index */, 200 /* status_code */, OK);
20364
20365 const NetworkErrorLoggingService::RequestDetails& error1 =
20366 network_error_logging_service()->errors()[0];
20367 const NetworkErrorLoggingService::RequestDetails& error2 =
20368 network_error_logging_service()->errors()[1];
20369
20370 // Sanity-check elapsed time values
20371 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20372 // Check that the start time is refreshed when restarting with auth.
20373 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20374}
20375
20376// Same as above, except draining the body before restarting fails
20377// asynchronously.
20378TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20379 CreateReportRestartWithAuthAsync) {
20380 std::string extra_header_string = extra_headers_.ToString();
20381 static const base::TimeDelta kSleepDuration =
20382 base::TimeDelta::FromMilliseconds(10);
20383
20384 MockWrite data_writes1[] = {
20385 MockWrite("GET / HTTP/1.1\r\n"
20386 "Host: www.example.org\r\n"
20387 "Connection: keep-alive\r\n"),
20388 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20389 };
20390
20391 MockRead data_reads1[] = {
20392 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20393 // Give a couple authenticate options (only the middle one is actually
20394 // supported).
20395 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20396 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20397 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20399 // Large content-length -- won't matter, as connection will be reset.
20400 MockRead("Content-Length: 10000\r\n\r\n"),
20401 MockRead(ASYNC, ERR_FAILED),
20402 };
20403
20404 // After calling trans->RestartWithAuth(), this is the request we should
20405 // be issuing -- the final header line contains the credentials.
20406 MockWrite data_writes2[] = {
20407 MockWrite("GET / HTTP/1.1\r\n"
20408 "Host: www.example.org\r\n"
20409 "Connection: keep-alive\r\n"
20410 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20411 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20412 };
20413
20414 // Lastly, the server responds with the actual content.
20415 MockRead data_reads2[] = {
20416 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20417 MockRead("hello world"),
20418 MockRead(SYNCHRONOUS, OK),
20419 };
20420
20421 StaticSocketDataProvider data1(data_reads1, data_writes1);
20422 StaticSocketDataProvider data2(data_reads2, data_writes2);
20423 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20424 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20425
20426 SSLSocketDataProvider ssl1(ASYNC, OK);
20427 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20428 SSLSocketDataProvider ssl2(ASYNC, OK);
20429 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20430
20431 base::TimeTicks start_time = base::TimeTicks::Now();
20432 base::TimeTicks restart_time;
20433
20434 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20435 auto trans =
20436 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20437
20438 TestCompletionCallback callback1;
20439
20440 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20441 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20442
20443 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20444
20445 TestCompletionCallback callback2;
20446
20447 // Wait 10 ms then restart with auth
20448 FastForwardBy(kSleepDuration);
20449 restart_time = base::TimeTicks::Now();
20450 rv =
20451 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20452 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20453
20454 std::string response_data;
20455 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20456 EXPECT_EQ("hello world", response_data);
20457
20458 trans.reset();
20459
20460 // One 401 report for the auth challenge, then a 200 report for the successful
20461 // retry. Note that we don't report the error draining the body, as the first
20462 // request already generated a report for the auth challenge.
20463 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20464
20465 // Check error report contents
20466 CheckReport(0 /* index */, 401 /* status_code */, OK);
20467 CheckReport(1 /* index */, 200 /* status_code */, OK);
20468
20469 const NetworkErrorLoggingService::RequestDetails& error1 =
20470 network_error_logging_service()->errors()[0];
20471 const NetworkErrorLoggingService::RequestDetails& error2 =
20472 network_error_logging_service()->errors()[1];
20473
20474 // Sanity-check elapsed time values
20475 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20476 // Check that the start time is refreshed when restarting with auth.
20477 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20478}
20479
20480TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20481 CreateReportRetryKeepAliveConnectionReset) {
20482 std::string extra_header_string = extra_headers_.ToString();
20483 MockWrite data_writes1[] = {
20484 MockWrite("GET / HTTP/1.1\r\n"
20485 "Host: www.example.org\r\n"
20486 "Connection: keep-alive\r\n"),
20487 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20488 MockWrite("GET / HTTP/1.1\r\n"
20489 "Host: www.example.org\r\n"
20490 "Connection: keep-alive\r\n"),
20491 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20492 };
20493
20494 MockRead data_reads1[] = {
20495 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20496 MockRead("hello"),
20497 // Connection is reset
20498 MockRead(ASYNC, ERR_CONNECTION_RESET),
20499 };
20500
20501 // Successful retry
20502 MockRead data_reads2[] = {
20503 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20504 MockRead("world"),
20505 MockRead(ASYNC, OK),
20506 };
20507
20508 StaticSocketDataProvider data1(data_reads1, data_writes1);
20509 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20510 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20511 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20512
20513 SSLSocketDataProvider ssl1(ASYNC, OK);
20514 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20515 SSLSocketDataProvider ssl2(ASYNC, OK);
20516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20517
20518 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20519 auto trans1 =
20520 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20521
20522 TestCompletionCallback callback1;
20523
20524 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20525 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20526
20527 std::string response_data;
20528 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20529 EXPECT_EQ("hello", response_data);
20530
20531 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20532
20533 auto trans2 =
20534 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20535
20536 TestCompletionCallback callback2;
20537
20538 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20539 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20540
20541 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20542 EXPECT_EQ("world", response_data);
20543
20544 trans1.reset();
20545 trans2.reset();
20546
20547 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20548 // the second request, then an OK report from the successful retry.
20549 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20550
20551 // Check error report contents
20552 CheckReport(0 /* index */, 200 /* status_code */, OK);
20553 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20554 CheckReport(2 /* index */, 200 /* status_code */, OK);
20555}
20556
20557TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20558 CreateReportRetryKeepAlive408) {
20559 std::string extra_header_string = extra_headers_.ToString();
20560 MockWrite data_writes1[] = {
20561 MockWrite("GET / HTTP/1.1\r\n"
20562 "Host: www.example.org\r\n"
20563 "Connection: keep-alive\r\n"),
20564 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20565 MockWrite("GET / HTTP/1.1\r\n"
20566 "Host: www.example.org\r\n"
20567 "Connection: keep-alive\r\n"),
20568 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20569 };
20570
20571 MockRead data_reads1[] = {
20572 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20573 MockRead("hello"),
20574 // 408 Request Timeout
20575 MockRead(SYNCHRONOUS,
20576 "HTTP/1.1 408 Request Timeout\r\n"
20577 "Connection: Keep-Alive\r\n"
20578 "Content-Length: 6\r\n\r\n"
20579 "Pickle"),
20580 };
20581
20582 // Successful retry
20583 MockRead data_reads2[] = {
20584 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20585 MockRead("world"),
20586 MockRead(ASYNC, OK),
20587 };
20588
20589 StaticSocketDataProvider data1(data_reads1, data_writes1);
20590 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20591 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20592 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20593
20594 SSLSocketDataProvider ssl1(ASYNC, OK);
20595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20596 SSLSocketDataProvider ssl2(ASYNC, OK);
20597 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20598
20599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20600 auto trans1 =
20601 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20602
20603 TestCompletionCallback callback1;
20604
20605 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20606 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20607
20608 std::string response_data;
20609 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20610 EXPECT_EQ("hello", response_data);
20611
20612 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20613
20614 auto trans2 =
20615 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20616
20617 TestCompletionCallback callback2;
20618
20619 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20620 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20621
20622 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20623 EXPECT_EQ("world", response_data);
20624
20625 trans1.reset();
20626 trans2.reset();
20627
20628 // One 200 report from first request, then a 408 report from
20629 // the second request, then a 200 report from the successful retry.
20630 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20631
20632 // Check error report contents
20633 CheckReport(0 /* index */, 200 /* status_code */, OK);
20634 CheckReport(1 /* index */, 408 /* status_code */, OK);
20635 CheckReport(2 /* index */, 200 /* status_code */, OK);
20636}
20637
20638TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20639 CreateReportRetry421WithoutConnectionPooling) {
20640 // Two hosts resolve to the same IP address.
20641 const std::string ip_addr = "1.2.3.4";
20642 IPAddress ip;
20643 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20644 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20645
20646 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20647 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20648 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20649
20650 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20651
20652 // Two requests on the first connection.
20653 spdy::SpdySerializedFrame req1(
20654 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20655 spdy_util_.UpdateWithStreamDestruction(1);
20656 spdy::SpdySerializedFrame req2(
20657 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20658 spdy::SpdySerializedFrame rst(
20659 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20660 MockWrite writes1[] = {
20661 CreateMockWrite(req1, 0),
20662 CreateMockWrite(req2, 3),
20663 CreateMockWrite(rst, 6),
20664 };
20665
20666 // The first one succeeds, the second gets error 421 Misdirected Request.
20667 spdy::SpdySerializedFrame resp1(
20668 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20669 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0120670 spdy::Http2HeaderBlock response_headers;
Lily Chenfec60d92019-01-24 01:16:4220671 response_headers[spdy::kHttp2StatusHeader] = "421";
20672 spdy::SpdySerializedFrame resp2(
20673 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20674 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20675 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20676
20677 MockConnect connect1(ASYNC, OK, peer_addr);
20678 SequencedSocketData data1(connect1, reads1, writes1);
20679 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20680
20681 AddSSLSocketData();
20682
20683 // Retry the second request on a second connection.
20684 SpdyTestUtil spdy_util2;
20685 spdy::SpdySerializedFrame req3(
20686 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20687 MockWrite writes2[] = {
20688 CreateMockWrite(req3, 0),
20689 };
20690
20691 spdy::SpdySerializedFrame resp3(
20692 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20693 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20694 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20695 MockRead(ASYNC, 0, 3)};
20696
20697 MockConnect connect2(ASYNC, OK, peer_addr);
20698 SequencedSocketData data2(connect2, reads2, writes2);
20699 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20700
20701 AddSSLSocketData();
20702
20703 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320704 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320705 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20706 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320707 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220708
20709 HttpRequestInfo request1;
20710 request1.method = "GET";
20711 request1.url = GURL("https://www.example.org/");
20712 request1.load_flags = 0;
20713 request1.traffic_annotation =
20714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20715 auto trans1 =
20716 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20717
Eric Orthf4db66a2019-02-19 21:35:3320718 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220719 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20720 EXPECT_THAT(callback.GetResult(rv), IsOk());
20721
20722 const HttpResponseInfo* response = trans1->GetResponseInfo();
20723 ASSERT_TRUE(response);
20724 ASSERT_TRUE(response->headers);
20725 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20726 EXPECT_TRUE(response->was_fetched_via_spdy);
20727 EXPECT_TRUE(response->was_alpn_negotiated);
20728 std::string response_data;
20729 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20730 EXPECT_EQ("hello!", response_data);
20731
20732 trans1.reset();
20733
20734 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20735
20736 HttpRequestInfo request2;
20737 request2.method = "GET";
20738 request2.url = GURL("https://mail.example.org/");
20739 request2.load_flags = 0;
20740 request2.traffic_annotation =
20741 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20742 auto trans2 =
20743 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20744
Matt Muellerd9342e3a2019-11-26 01:41:1420745 RecordingBoundTestNetLog log;
Lily Chenfec60d92019-01-24 01:16:4220746 rv = trans2->Start(&request2, callback.callback(), log.bound());
20747 EXPECT_THAT(callback.GetResult(rv), IsOk());
20748
20749 response = trans2->GetResponseInfo();
20750 ASSERT_TRUE(response);
20751 ASSERT_TRUE(response->headers);
20752 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20753 EXPECT_TRUE(response->was_fetched_via_spdy);
20754 EXPECT_TRUE(response->was_alpn_negotiated);
20755 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20756 EXPECT_EQ("hello!", response_data);
20757
20758 trans2.reset();
20759
20760 // One 200 report from the first request, then a 421 report from the
20761 // second request, then a 200 report from the successful retry.
20762 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20763
20764 // Check error report contents
20765 const NetworkErrorLoggingService::RequestDetails& error1 =
20766 network_error_logging_service()->errors()[0];
20767 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20768 EXPECT_TRUE(error1.referrer.is_empty());
20769 EXPECT_EQ("", error1.user_agent);
20770 EXPECT_EQ(ip, error1.server_ip);
20771 EXPECT_EQ("h2", error1.protocol);
20772 EXPECT_EQ("GET", error1.method);
20773 EXPECT_EQ(200, error1.status_code);
20774 EXPECT_EQ(OK, error1.type);
20775 EXPECT_EQ(0, error1.reporting_upload_depth);
20776
20777 const NetworkErrorLoggingService::RequestDetails& error2 =
20778 network_error_logging_service()->errors()[1];
20779 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20780 EXPECT_TRUE(error2.referrer.is_empty());
20781 EXPECT_EQ("", error2.user_agent);
20782 EXPECT_EQ(ip, error2.server_ip);
20783 EXPECT_EQ("h2", error2.protocol);
20784 EXPECT_EQ("GET", error2.method);
20785 EXPECT_EQ(421, error2.status_code);
20786 EXPECT_EQ(OK, error2.type);
20787 EXPECT_EQ(0, error2.reporting_upload_depth);
20788
20789 const NetworkErrorLoggingService::RequestDetails& error3 =
20790 network_error_logging_service()->errors()[2];
20791 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20792 EXPECT_TRUE(error3.referrer.is_empty());
20793 EXPECT_EQ("", error3.user_agent);
20794 EXPECT_EQ(ip, error3.server_ip);
20795 EXPECT_EQ("h2", error3.protocol);
20796 EXPECT_EQ("GET", error3.method);
20797 EXPECT_EQ(200, error3.status_code);
20798 EXPECT_EQ(OK, error3.type);
20799 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620800}
20801
Lily Chend3930e72019-03-01 19:31:1120802TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20803 CreateReportCancelAfterStart) {
20804 StaticSocketDataProvider data;
20805 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20806 session_deps_.socket_factory->AddSocketDataProvider(&data);
20807
20808 TestCompletionCallback callback;
20809 auto session = CreateSession(&session_deps_);
20810 auto trans =
20811 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20812 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20813 EXPECT_EQ(rv, ERR_IO_PENDING);
20814
20815 // Cancel after start.
20816 trans.reset();
20817
20818 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20819 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20820 IPAddress() /* server_ip */);
20821}
20822
20823TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20824 CreateReportCancelBeforeReadingBody) {
20825 std::string extra_header_string = extra_headers_.ToString();
20826 MockWrite data_writes[] = {
20827 MockWrite("GET / HTTP/1.1\r\n"
20828 "Host: www.example.org\r\n"
20829 "Connection: keep-alive\r\n"),
20830 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20831 };
20832 MockRead data_reads[] = {
20833 MockRead("HTTP/1.0 200 OK\r\n"),
20834 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20835 };
20836
20837 StaticSocketDataProvider data(data_reads, data_writes);
20838 session_deps_.socket_factory->AddSocketDataProvider(&data);
20839
20840 SSLSocketDataProvider ssl(ASYNC, OK);
20841 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20842
20843 TestCompletionCallback callback;
20844 auto session = CreateSession(&session_deps_);
20845 auto trans =
20846 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20847 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20848 EXPECT_THAT(callback.GetResult(rv), IsOk());
20849
20850 const HttpResponseInfo* response = trans->GetResponseInfo();
20851 ASSERT_TRUE(response);
20852
20853 EXPECT_TRUE(response->headers);
20854 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20855
20856 // Cancel before reading the body.
20857 trans.reset();
20858
20859 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20860 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20861}
20862
Lily Chen00196ab62018-12-04 19:52:2920863TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
Lily Chen00196ab62018-12-04 19:52:2920864 RequestPolicy();
20865 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20866 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20867
20868 // Make HTTP request
20869 std::string extra_header_string = extra_headers_.ToString();
20870 MockRead data_reads[] = {
20871 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20872 MockRead("hello world"),
20873 MockRead(SYNCHRONOUS, OK),
20874 };
20875 MockWrite data_writes[] = {
20876 MockWrite("GET / HTTP/1.1\r\n"
20877 "Host: www.example.org\r\n"
20878 "Connection: keep-alive\r\n"),
20879 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20880 };
20881
Lily Chend3930e72019-03-01 19:31:1120882 StaticSocketDataProvider data(data_reads, data_writes);
20883 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920884
Lily Chenfec60d92019-01-24 01:16:4220885 // Insecure url
20886 url_ = "http://www.example.org/";
20887 request_.url = GURL(url_);
20888
Lily Chen00196ab62018-12-04 19:52:2920889 TestCompletionCallback callback;
20890 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220891 auto trans =
20892 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20893 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20894 EXPECT_THAT(callback.GetResult(rv), IsOk());
20895
20896 std::string response_data;
20897 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20898 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920899
20900 // Insecure request does not generate a report
Lily Chen00196ab62018-12-04 19:52:2920901 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20902}
20903
20904TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20905 DontCreateReportHttpError) {
Lily Chen00196ab62018-12-04 19:52:2920906 RequestPolicy();
20907 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20908 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20909
20910 // Make HTTP request that fails
20911 MockRead data_reads[] = {
20912 MockRead("hello world"),
20913 MockRead(SYNCHRONOUS, OK),
20914 };
20915
20916 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20917 session_deps_.socket_factory->AddSocketDataProvider(&data);
20918
Lily Chenfec60d92019-01-24 01:16:4220919 url_ = "http://www.originwithoutpolicy.com:2000/";
20920 request_.url = GURL(url_);
20921
Lily Chen00196ab62018-12-04 19:52:2920922 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20923
Lily Chen00196ab62018-12-04 19:52:2920924 auto trans =
20925 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920926 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220927 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920928 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20929
20930 // Insecure request does not generate a report, regardless of existence of a
20931 // policy for the origin.
Lily Chen00196ab62018-12-04 19:52:2920932 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20933}
20934
Lily Chen90ae93cc2019-02-14 01:15:3920935// Don't report on proxy auth challenges, don't report if connecting through a
20936// proxy.
20937TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20938 HttpRequestInfo request;
20939 request.method = "GET";
20940 request.url = GURL("https://www.example.org/");
20941 request.traffic_annotation =
20942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20943
20944 // Configure against proxy server "myproxy:70".
20945 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620946 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920947 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20948 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20949
20950 // Since we have proxy, should try to establish tunnel.
20951 MockWrite data_writes1[] = {
20952 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20953 "Host: www.example.org:443\r\n"
20954 "Proxy-Connection: keep-alive\r\n\r\n"),
20955 };
20956
20957 // The proxy responds to the connect with a 407, using a non-persistent
20958 // connection.
20959 MockRead data_reads1[] = {
20960 // No credentials.
20961 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20962 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20963 MockRead("Proxy-Connection: close\r\n\r\n"),
20964 };
20965
20966 MockWrite data_writes2[] = {
20967 // After calling trans->RestartWithAuth(), this is the request we should
20968 // be issuing -- the final header line contains the credentials.
20969 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20970 "Host: www.example.org:443\r\n"
20971 "Proxy-Connection: keep-alive\r\n"
20972 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20973
20974 MockWrite("GET / HTTP/1.1\r\n"
20975 "Host: www.example.org\r\n"
20976 "Connection: keep-alive\r\n\r\n"),
20977 };
20978
20979 MockRead data_reads2[] = {
20980 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20981
20982 MockRead("HTTP/1.1 200 OK\r\n"),
20983 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20984 MockRead("Content-Length: 5\r\n\r\n"),
20985 MockRead(SYNCHRONOUS, "hello"),
20986 };
20987
20988 StaticSocketDataProvider data1(data_reads1, data_writes1);
20989 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20990 StaticSocketDataProvider data2(data_reads2, data_writes2);
20991 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20992 SSLSocketDataProvider ssl(ASYNC, OK);
20993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20994
20995 TestCompletionCallback callback1;
20996
20997 auto trans =
20998 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20999
21000 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
21001 EXPECT_THAT(callback1.GetResult(rv), IsOk());
21002
21003 const HttpResponseInfo* response = trans->GetResponseInfo();
21004 EXPECT_EQ(407, response->headers->response_code());
21005
21006 std::string response_data;
21007 rv = ReadTransaction(trans.get(), &response_data);
21008 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
21009
21010 // No NEL report is generated for the 407.
21011 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
21012
21013 TestCompletionCallback callback2;
21014
21015 rv =
21016 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
21017 EXPECT_THAT(callback2.GetResult(rv), IsOk());
21018
21019 response = trans->GetResponseInfo();
21020 EXPECT_EQ(200, response->headers->response_code());
21021
21022 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
21023 EXPECT_EQ("hello", response_data);
21024
21025 trans.reset();
21026
21027 // No NEL report is generated because we are behind a proxy.
21028 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
21029}
21030
Douglas Creageref5eecdc2018-11-09 20:50:3621031TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
21032 ReportContainsUploadDepth) {
21033 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4221034 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3621035 RequestPolicy();
21036 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4221037 const NetworkErrorLoggingService::RequestDetails& error =
21038 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3621039 EXPECT_EQ(7, error.reporting_upload_depth);
21040}
21041
Lily Chenfec60d92019-01-24 01:16:4221042TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
21043 std::string extra_header_string = extra_headers_.ToString();
21044 static const base::TimeDelta kSleepDuration =
21045 base::TimeDelta::FromMilliseconds(10);
21046
21047 std::vector<MockWrite> data_writes = {
21048 MockWrite(ASYNC, 0,
21049 "GET / HTTP/1.1\r\n"
21050 "Host: www.example.org\r\n"
21051 "Connection: keep-alive\r\n"),
21052 MockWrite(ASYNC, 1, extra_header_string.data()),
21053 };
21054
21055 std::vector<MockRead> data_reads = {
21056 // Write one byte of the status line, followed by a pause.
21057 MockRead(ASYNC, 2, "H"),
21058 MockRead(ASYNC, ERR_IO_PENDING, 3),
21059 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
21060 MockRead(ASYNC, 5, "hello world"),
21061 MockRead(SYNCHRONOUS, OK, 6),
21062 };
21063
21064 SequencedSocketData data(data_reads, data_writes);
21065 session_deps_.socket_factory->AddSocketDataProvider(&data);
21066
21067 SSLSocketDataProvider ssl(ASYNC, OK);
21068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21069
21070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21071
21072 auto trans =
21073 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21074
21075 TestCompletionCallback callback;
21076
21077 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
21078 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21079
21080 data.RunUntilPaused();
21081 ASSERT_TRUE(data.IsPaused());
21082 FastForwardBy(kSleepDuration);
21083 data.Resume();
21084
21085 EXPECT_THAT(callback.GetResult(rv), IsOk());
21086
21087 std::string response_data;
21088 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
21089 EXPECT_EQ("hello world", response_data);
21090
21091 trans.reset();
21092
Douglas Creageref5eecdc2018-11-09 20:50:3621093 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4221094
21095 CheckReport(0 /* index */, 200 /* status_code */, OK);
21096
21097 const NetworkErrorLoggingService::RequestDetails& error =
21098 network_error_logging_service()->errors()[0];
21099
21100 // Sanity-check elapsed time in error report
21101 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3621102}
Lily Chenfec60d92019-01-24 01:16:4221103
Douglas Creager3cb042052018-11-06 23:08:5221104#endif // BUILDFLAG(ENABLE_REPORTING)
21105
Batalov Vladislava4e97a502019-04-11 15:35:2321106TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
21107 HttpRequestInfo request;
21108 request.method = "GET";
21109 request.url = GURL("http://example.org/");
21110
21111 request.load_flags = LOAD_ONLY_FROM_CACHE;
21112
21113 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21115 TestCompletionCallback callback1;
21116 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
21117
21118 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
21119}
21120
Steven Valdez1c1859172019-04-10 15:33:2821121TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1521122 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821123 HttpRequestInfo request;
21124 request.method = "GET";
21125 request.url = GURL("https://www.example.org/");
21126 request.traffic_annotation =
21127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21128
21129 MockWrite data_writes[] = {
21130 MockWrite("GET / HTTP/1.1\r\n"
21131 "Host: www.example.org\r\n"
21132 "Connection: keep-alive\r\n\r\n"),
21133 };
21134
Steven Valdez1c1859172019-04-10 15:33:2821135 MockRead data_reads[] = {
21136 MockRead("HTTP/1.1 200 OK\r\n"),
21137 MockRead("Content-Length: 1\r\n\r\n"),
21138 MockRead(SYNCHRONOUS, "1"),
21139 };
21140
21141 StaticSocketDataProvider data(data_reads, data_writes);
21142 session_deps_.socket_factory->AddSocketDataProvider(&data);
21143 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521144 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821145 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521146 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821147 session_deps_.enable_early_data = true;
21148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21149
21150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21151
21152 TestCompletionCallback callback;
21153 auto trans =
21154 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21155
David Benjaminbae08ba2019-10-18 21:06:1521156 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821157 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21158 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21159
21160 rv = callback.WaitForResult();
21161 EXPECT_THAT(rv, IsOk());
21162
21163 const HttpResponseInfo* response = trans->GetResponseInfo();
21164 ASSERT_TRUE(response);
21165 ASSERT_TRUE(response->headers);
21166 EXPECT_EQ(200, response->headers->response_code());
21167 EXPECT_EQ(1, response->headers->GetContentLength());
21168
21169 // Check that ConfirmHandshake wasn't called.
21170 ASSERT_FALSE(ssl.ConfirmDataConsumed());
21171 ASSERT_TRUE(ssl.WriteBeforeConfirm());
21172
David Benjaminbae08ba2019-10-18 21:06:1521173 // The handshake time should include the time it took to run Connect(), but
21174 // not ConfirmHandshake().
21175 LoadTimingInfo load_timing_info;
21176 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21177 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21178 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21179 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21180 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21181
Steven Valdez1c1859172019-04-10 15:33:2821182 trans.reset();
21183
Matt Menke433de6d2020-03-04 00:24:1121184 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821185}
21186
21187TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521188 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821189 HttpRequestInfo request;
21190 request.method = "POST";
21191 request.url = GURL("https://www.example.org/");
21192 request.traffic_annotation =
21193 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21194
21195 MockWrite data_writes[] = {
21196 MockWrite(SYNCHRONOUS,
21197 "POST / HTTP/1.1\r\n"
21198 "Host: www.example.org\r\n"
21199 "Connection: keep-alive\r\n"
21200 "Content-Length: 0\r\n\r\n"),
21201 };
21202
Steven Valdez1c1859172019-04-10 15:33:2821203 MockRead data_reads[] = {
21204 MockRead("HTTP/1.1 200 OK\r\n"),
21205 MockRead("Content-Length: 1\r\n\r\n"),
21206 MockRead(SYNCHRONOUS, "1"),
21207 };
21208
21209 StaticSocketDataProvider data(data_reads, data_writes);
21210 session_deps_.socket_factory->AddSocketDataProvider(&data);
21211 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521212 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821213 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521214 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821215 session_deps_.enable_early_data = true;
21216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21217
21218 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21219
21220 TestCompletionCallback callback;
21221 auto trans =
21222 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21223
David Benjaminbae08ba2019-10-18 21:06:1521224 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821225 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21227
21228 rv = callback.WaitForResult();
21229 EXPECT_THAT(rv, IsOk());
21230
21231 const HttpResponseInfo* response = trans->GetResponseInfo();
21232 ASSERT_TRUE(response);
21233 ASSERT_TRUE(response->headers);
21234 EXPECT_EQ(200, response->headers->response_code());
21235 EXPECT_EQ(1, response->headers->GetContentLength());
21236
21237 // Check that the Write didn't get called before ConfirmHandshake completed.
21238 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21239
David Benjaminbae08ba2019-10-18 21:06:1521240 // The handshake time should include the time it took to run Connect(), but
21241 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
21242 // assume the connection did not negotiate 0-RTT or the handshake was already
21243 // confirmed.
21244 LoadTimingInfo load_timing_info;
21245 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21246 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21247 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21248 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21249 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21250
Steven Valdez1c1859172019-04-10 15:33:2821251 trans.reset();
21252
Matt Menke433de6d2020-03-04 00:24:1121253 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821254}
21255
21256TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
21257 HttpRequestInfo request;
21258 request.method = "POST";
21259 request.url = GURL("https://www.example.org/");
21260 request.traffic_annotation =
21261 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21262
21263 MockWrite data_writes[] = {
21264 MockWrite(ASYNC,
21265 "POST / HTTP/1.1\r\n"
21266 "Host: www.example.org\r\n"
21267 "Connection: keep-alive\r\n"
21268 "Content-Length: 0\r\n\r\n"),
21269 };
21270
Steven Valdez1c1859172019-04-10 15:33:2821271 MockRead data_reads[] = {
21272 MockRead("HTTP/1.1 200 OK\r\n"),
21273 MockRead("Content-Length: 1\r\n\r\n"),
21274 MockRead(SYNCHRONOUS, "1"),
21275 };
21276
21277 StaticSocketDataProvider data(data_reads, data_writes);
21278 session_deps_.socket_factory->AddSocketDataProvider(&data);
21279 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21280 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
21281 session_deps_.enable_early_data = true;
21282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21283
21284 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21285
21286 TestCompletionCallback callback;
21287 auto trans =
21288 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21289
21290 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21292
21293 rv = callback.WaitForResult();
21294 EXPECT_THAT(rv, IsOk());
21295
21296 const HttpResponseInfo* response = trans->GetResponseInfo();
21297 ASSERT_TRUE(response);
21298 ASSERT_TRUE(response->headers);
21299 EXPECT_EQ(200, response->headers->response_code());
21300 EXPECT_EQ(1, response->headers->GetContentLength());
21301
21302 // Check that the Write didn't get called before ConfirmHandshake completed.
21303 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21304
21305 trans.reset();
21306
Matt Menke433de6d2020-03-04 00:24:1121307 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821308}
21309
21310TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521311 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821312 HttpRequestInfo request;
21313 request.method = "POST";
21314 request.url = GURL("https://www.example.org/");
21315 request.traffic_annotation =
21316 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21317
21318 MockWrite data_writes[] = {
21319 MockWrite(SYNCHRONOUS,
21320 "POST / HTTP/1.1\r\n"
21321 "Host: www.example.org\r\n"
21322 "Connection: keep-alive\r\n"
21323 "Content-Length: 0\r\n\r\n"),
21324 };
21325
Steven Valdez1c1859172019-04-10 15:33:2821326 MockRead data_reads[] = {
21327 MockRead("HTTP/1.1 200 OK\r\n"),
21328 MockRead("Content-Length: 1\r\n\r\n"),
21329 MockRead(SYNCHRONOUS, "1"),
21330 };
21331
21332 StaticSocketDataProvider data(data_reads, data_writes);
21333 session_deps_.socket_factory->AddSocketDataProvider(&data);
21334 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521335 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821336 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1521337 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821338 session_deps_.enable_early_data = true;
21339 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21340
21341 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21342
21343 TestCompletionCallback callback;
21344 auto trans =
21345 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21346
David Benjaminbae08ba2019-10-18 21:06:1521347 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821348 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21350
21351 rv = callback.WaitForResult();
21352 EXPECT_THAT(rv, IsOk());
21353
21354 const HttpResponseInfo* response = trans->GetResponseInfo();
21355 ASSERT_TRUE(response);
21356 ASSERT_TRUE(response->headers);
21357 EXPECT_EQ(200, response->headers->response_code());
21358 EXPECT_EQ(1, response->headers->GetContentLength());
21359
21360 // Check that the Write didn't get called before ConfirmHandshake completed.
21361 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21362
David Benjaminbae08ba2019-10-18 21:06:1521363 // The handshake time should include the time it took to run Connect() and
21364 // ConfirmHandshake().
21365 LoadTimingInfo load_timing_info;
21366 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21367 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21368 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21369 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
21370 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
21371 start_time + 2 * kDelay);
21372
Steven Valdez1c1859172019-04-10 15:33:2821373 trans.reset();
21374
Matt Menke433de6d2020-03-04 00:24:1121375 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821376}
21377
21378TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
21379 HttpRequestInfo request;
21380 request.method = "POST";
21381 request.url = GURL("https://www.example.org/");
21382 request.traffic_annotation =
21383 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21384
21385 MockWrite data_writes[] = {
21386 MockWrite(ASYNC,
21387 "POST / HTTP/1.1\r\n"
21388 "Host: www.example.org\r\n"
21389 "Connection: keep-alive\r\n"
21390 "Content-Length: 0\r\n\r\n"),
21391 };
21392
Steven Valdez1c1859172019-04-10 15:33:2821393 MockRead data_reads[] = {
21394 MockRead("HTTP/1.1 200 OK\r\n"),
21395 MockRead("Content-Length: 1\r\n\r\n"),
21396 MockRead(SYNCHRONOUS, "1"),
21397 };
21398
21399 StaticSocketDataProvider data(data_reads, data_writes);
21400 session_deps_.socket_factory->AddSocketDataProvider(&data);
21401 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21402 ssl.confirm = MockConfirm(ASYNC, OK);
21403 session_deps_.enable_early_data = true;
21404 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21405
21406 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21407
21408 TestCompletionCallback callback;
21409 auto trans =
21410 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21411
21412 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21413 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21414
21415 rv = callback.WaitForResult();
21416 EXPECT_THAT(rv, IsOk());
21417
21418 const HttpResponseInfo* response = trans->GetResponseInfo();
21419 ASSERT_TRUE(response);
21420 ASSERT_TRUE(response->headers);
21421 EXPECT_EQ(200, response->headers->response_code());
21422 EXPECT_EQ(1, response->headers->GetContentLength());
21423
21424 // Check that the Write didn't get called before ConfirmHandshake completed.
21425 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21426
21427 trans.reset();
21428
Matt Menke433de6d2020-03-04 00:24:1121429 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821430}
21431
David Benjaminfb976932019-05-15 13:39:1521432// 0-RTT rejects are handled at HttpNetworkTransaction.
21433TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
21434 enum class RejectType {
21435 kRead,
21436 kWrite,
21437 kConfirm,
21438 };
21439
21440 for (RejectType type :
21441 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
21442 SCOPED_TRACE(static_cast<int>(type));
21443 for (Error reject_error :
21444 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
21445 SCOPED_TRACE(reject_error);
21446 session_deps_.socket_factory =
21447 std::make_unique<MockClientSocketFactory>();
21448
21449 HttpRequestInfo request;
21450 request.method = type == RejectType::kConfirm ? "POST" : "GET";
21451 request.url = GURL("https://www.example.org/");
21452 request.traffic_annotation =
21453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21454
21455 // The first request fails.
21456 std::vector<MockWrite> data1_writes;
21457 std::vector<MockRead> data1_reads;
21458 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
21459 switch (type) {
21460 case RejectType::kRead:
21461 data1_writes.emplace_back(
21462 "GET / HTTP/1.1\r\n"
21463 "Host: www.example.org\r\n"
21464 "Connection: keep-alive\r\n\r\n");
21465 data1_reads.emplace_back(ASYNC, reject_error);
21466 // Cause ConfirmHandshake to hang (it should not be called).
21467 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21468 break;
21469 case RejectType::kWrite:
21470 data1_writes.emplace_back(ASYNC, reject_error);
21471 // Cause ConfirmHandshake to hang (it should not be called).
21472 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21473 break;
21474 case RejectType::kConfirm:
21475 // The request never gets far enough to read or write.
21476 ssl1.confirm = MockConfirm(ASYNC, reject_error);
21477 break;
21478 }
21479
21480 StaticSocketDataProvider data1(data1_reads, data1_writes);
21481 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21482 session_deps_.enable_early_data = true;
21483 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21484
21485 // The retry succeeds.
21486 //
21487 // TODO(https://crbug.com/950705): If |reject_error| is
21488 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
21489 MockWrite data2_writes[] = {
21490 request.method == "POST"
21491 ? MockWrite("POST / HTTP/1.1\r\n"
21492 "Host: www.example.org\r\n"
21493 "Connection: keep-alive\r\n"
21494 "Content-Length: 0\r\n\r\n")
21495 : MockWrite("GET / HTTP/1.1\r\n"
21496 "Host: www.example.org\r\n"
21497 "Connection: keep-alive\r\n\r\n"),
21498 };
21499
21500 MockRead data2_reads[] = {
21501 MockRead("HTTP/1.1 200 OK\r\n"),
21502 MockRead("Content-Length: 1\r\n\r\n"),
21503 MockRead(SYNCHRONOUS, "1"),
21504 };
21505
21506 StaticSocketDataProvider data2(data2_reads, data2_writes);
21507 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21508 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21509 ssl2.confirm = MockConfirm(ASYNC, OK);
21510 session_deps_.enable_early_data = true;
21511 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21512
21513 std::unique_ptr<HttpNetworkSession> session(
21514 CreateSession(&session_deps_));
21515
21516 TestCompletionCallback callback;
21517 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21518 session.get());
21519
21520 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21521 NetLogWithSource())),
21522 IsOk());
21523
21524 const HttpResponseInfo* response = trans->GetResponseInfo();
21525 ASSERT_TRUE(response);
21526 ASSERT_TRUE(response->headers);
21527 EXPECT_EQ(200, response->headers->response_code());
21528 EXPECT_EQ(1, response->headers->GetContentLength());
21529 }
21530 }
21531}
21532
Steven Valdez1c1859172019-04-10 15:33:2821533TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21534 HttpRequestInfo request;
21535 request.method = "POST";
21536 request.url = GURL("https://www.example.org/");
21537 request.traffic_annotation =
21538 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21539
21540 MockWrite data_writes[] = {
21541 MockWrite("POST / HTTP/1.1\r\n"
21542 "Host: www.example.org\r\n"
21543 "Connection: keep-alive\r\n"
21544 "Content-Length: 0\r\n\r\n"),
21545 };
21546
Steven Valdez1c1859172019-04-10 15:33:2821547 MockRead data_reads[] = {
21548 MockRead("HTTP/1.1 200 OK\r\n"),
21549 MockRead("Content-Length: 1\r\n\r\n"),
21550 MockRead(SYNCHRONOUS, "1"),
21551 };
21552
21553 StaticSocketDataProvider data(data_reads, data_writes);
21554 session_deps_.socket_factory->AddSocketDataProvider(&data);
21555 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21556 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21557 session_deps_.enable_early_data = true;
21558 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21559
21560 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21561
21562 TestCompletionCallback callback;
21563 auto trans =
21564 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21565
21566 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21567 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21568
21569 rv = callback.WaitForResult();
21570 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21571
21572 // Check that the Write didn't get called before ConfirmHandshake completed.
21573 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21574
21575 trans.reset();
21576
Matt Menke433de6d2020-03-04 00:24:1121577 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821578}
21579
21580TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21581 HttpRequestInfo request;
21582 request.method = "POST";
21583 request.url = GURL("https://www.example.org/");
21584 request.traffic_annotation =
21585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21586
21587 MockWrite data_writes[] = {
21588 MockWrite("POST / HTTP/1.1\r\n"
21589 "Host: www.example.org\r\n"
21590 "Connection: keep-alive\r\n"
21591 "Content-Length: 0\r\n\r\n"),
21592 };
21593
Steven Valdez1c1859172019-04-10 15:33:2821594 MockRead data_reads[] = {
21595 MockRead("HTTP/1.1 200 OK\r\n"),
21596 MockRead("Content-Length: 1\r\n\r\n"),
21597 MockRead(SYNCHRONOUS, "1"),
21598 };
21599
21600 StaticSocketDataProvider data(data_reads, data_writes);
21601 session_deps_.socket_factory->AddSocketDataProvider(&data);
21602 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21603 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21604 session_deps_.enable_early_data = true;
21605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21606
21607 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21608
21609 TestCompletionCallback callback;
21610 auto trans =
21611 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21612
21613 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21614 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21615
21616 rv = callback.WaitForResult();
21617 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21618
21619 // Check that the Write didn't get called before ConfirmHandshake completed.
21620 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21621
21622 trans.reset();
21623
Matt Menke433de6d2020-03-04 00:24:1121624 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821625}
21626
David Benjamin2eb827f2019-04-29 18:31:0421627// Test the proxy and origin server each requesting both TLS client certificates
21628// and HTTP auth. This is a regression test for https://crbug.com/946406.
21629TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21630 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621631 session_deps_.proxy_resolution_service =
21632 ConfiguredProxyResolutionService::CreateFixed(
21633 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421634
21635 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21636 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21637
21638 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21639 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21640 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21641 ASSERT_TRUE(identity_proxy);
21642
21643 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21644 cert_request_info_origin->host_and_port =
21645 HostPortPair("www.example.org", 443);
21646
21647 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21648 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21649 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21650 ASSERT_TRUE(identity_origin);
21651
21652 HttpRequestInfo request;
21653 request.method = "GET";
21654 request.url = GURL("https://www.example.org/");
21655 request.traffic_annotation =
21656 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21657
David Benjamin7ebab032019-04-30 21:51:3021658 // First, the client connects to the proxy, which requests a client
21659 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421660 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21661 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21662 ssl_proxy1.expected_send_client_cert = false;
21663 StaticSocketDataProvider data1;
21664 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421666
David Benjamin7ebab032019-04-30 21:51:3021667 // The client responds with a certificate on a new connection. The handshake
21668 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421669 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21670 ssl_proxy2.expected_send_client_cert = true;
21671 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021672 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421673 std::vector<MockWrite> mock_writes2;
21674 std::vector<MockRead> mock_reads2;
21675 mock_writes2.emplace_back(
21676 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21677 "Host: www.example.org:443\r\n"
21678 "Proxy-Connection: keep-alive\r\n\r\n");
21679 mock_reads2.emplace_back(
21680 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21681 "Content-Length: 0\r\n"
21682 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021683 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421684 mock_writes2.emplace_back(
21685 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21686 "Host: www.example.org:443\r\n"
21687 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021688 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421689 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21690 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21691 // The origin requests client certificates.
21692 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21693 ssl_origin2.cert_request_info = cert_request_info_origin.get();
21694 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21695 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021696 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421698
David Benjamin7ebab032019-04-30 21:51:3021699 // The client responds to the origin client certificate request on a new
21700 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421701 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21702 ssl_proxy3.expected_send_client_cert = true;
21703 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21704 std::vector<MockWrite> mock_writes3;
21705 std::vector<MockRead> mock_reads3;
21706 mock_writes3.emplace_back(
21707 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21708 "Host: www.example.org:443\r\n"
21709 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021710 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421711 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21712 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21713 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21714 ssl_origin3.expected_send_client_cert = true;
21715 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021716 // The client sends the origin HTTP request, which results in another HTTP
21717 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421718 mock_writes3.emplace_back(
21719 "GET / HTTP/1.1\r\n"
21720 "Host: www.example.org\r\n"
21721 "Connection: keep-alive\r\n\r\n");
21722 mock_reads3.emplace_back(
21723 "HTTP/1.1 401 Unauthorized\r\n"
21724 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21725 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021726 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421727 mock_writes3.emplace_back(
21728 "GET / HTTP/1.1\r\n"
21729 "Host: www.example.org\r\n"
21730 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021731 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421732 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21733 mock_reads3.emplace_back(
21734 "HTTP/1.1 200 OK\r\n"
21735 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121736 // The client makes another request. This should reuse the socket with all
21737 // credentials cached.
21738 mock_writes3.emplace_back(
21739 "GET / HTTP/1.1\r\n"
21740 "Host: www.example.org\r\n"
21741 "Connection: keep-alive\r\n"
21742 // Authenticate as user:pass.
21743 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21744 mock_reads3.emplace_back(
21745 "HTTP/1.1 200 OK\r\n"
21746 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421747 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21748 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21750 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421751
21752 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21753
21754 // Start the request.
21755 TestCompletionCallback callback;
21756 auto trans =
21757 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21758 int rv = callback.GetResult(
21759 trans->Start(&request, callback.callback(), NetLogWithSource()));
21760
21761 // Handle the proxy client certificate challenge.
21762 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21763 SSLCertRequestInfo* cert_request_info =
21764 trans->GetResponseInfo()->cert_request_info.get();
21765 ASSERT_TRUE(cert_request_info);
21766 EXPECT_TRUE(cert_request_info->is_proxy);
21767 EXPECT_EQ(cert_request_info->host_and_port,
21768 cert_request_info_proxy->host_and_port);
21769 rv = callback.GetResult(trans->RestartWithCertificate(
21770 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21771 callback.callback()));
21772
21773 // Handle the proxy HTTP auth challenge.
21774 ASSERT_THAT(rv, IsOk());
21775 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21776 EXPECT_TRUE(
21777 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21778 rv = callback.GetResult(trans->RestartWithAuth(
21779 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21780 callback.callback()));
21781
21782 // Handle the origin client certificate challenge.
21783 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21784 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21785 ASSERT_TRUE(cert_request_info);
21786 EXPECT_FALSE(cert_request_info->is_proxy);
21787 EXPECT_EQ(cert_request_info->host_and_port,
21788 cert_request_info_origin->host_and_port);
21789 rv = callback.GetResult(trans->RestartWithCertificate(
21790 identity_origin->certificate(), identity_origin->ssl_private_key(),
21791 callback.callback()));
21792
21793 // Handle the origin HTTP auth challenge.
21794 ASSERT_THAT(rv, IsOk());
21795 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21796 EXPECT_TRUE(
21797 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21798 rv = callback.GetResult(trans->RestartWithAuth(
21799 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21800 callback.callback()));
21801
21802 // The request completes.
21803 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021804 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121805
21806 // Make a second request. This time all credentials are cached.
21807 trans =
21808 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21809 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21810 NetLogWithSource())),
21811 IsOk());
21812 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421813}
21814
21815// Test the proxy and origin server each requesting both TLS client certificates
21816// and HTTP auth and each HTTP auth closing the connection. This is a regression
21817// test for https://crbug.com/946406.
21818TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21819 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621820 session_deps_.proxy_resolution_service =
21821 ConfiguredProxyResolutionService::CreateFixed(
21822 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421823
21824 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21825 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21826
21827 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21828 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21829 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21830 ASSERT_TRUE(identity_proxy);
21831
21832 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21833 cert_request_info_origin->host_and_port =
21834 HostPortPair("www.example.org", 443);
21835
21836 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21837 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21838 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21839 ASSERT_TRUE(identity_origin);
21840
21841 HttpRequestInfo request;
21842 request.method = "GET";
21843 request.url = GURL("https://www.example.org/");
21844 request.traffic_annotation =
21845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21846
David Benjamin7ebab032019-04-30 21:51:3021847 // First, the client connects to the proxy, which requests a client
21848 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421849 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21850 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21851 ssl_proxy1.expected_send_client_cert = false;
21852 StaticSocketDataProvider data1;
21853 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021854 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421855
David Benjamin7ebab032019-04-30 21:51:3021856 // The client responds with a certificate on a new connection. The handshake
21857 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421858 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21859 ssl_proxy2.expected_send_client_cert = true;
21860 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021861 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421862 std::vector<MockWrite> mock_writes2;
21863 std::vector<MockRead> mock_reads2;
21864 mock_writes2.emplace_back(
21865 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21866 "Host: www.example.org:443\r\n"
21867 "Proxy-Connection: keep-alive\r\n\r\n");
21868 mock_reads2.emplace_back(
21869 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21870 "Content-Length: 0\r\n"
21871 "Proxy-Connection: close\r\n"
21872 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21873 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21874 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421876
David Benjamin7ebab032019-04-30 21:51:3021877 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421878 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21879 ssl_proxy3.expected_send_client_cert = true;
21880 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21881 std::vector<MockWrite> mock_writes3;
21882 std::vector<MockRead> mock_reads3;
21883 mock_writes3.emplace_back(
21884 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21885 "Host: www.example.org:443\r\n"
21886 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021887 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421888 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21889 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21890 // The origin requests client certificates.
21891 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21892 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21893 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21894 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421897
David Benjamin7ebab032019-04-30 21:51:3021898 // The client responds to the origin client certificate request on a new
21899 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421900 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21901 ssl_proxy4.expected_send_client_cert = true;
21902 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21903 std::vector<MockWrite> mock_writes4;
21904 std::vector<MockRead> mock_reads4;
21905 mock_writes4.emplace_back(
21906 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21907 "Host: www.example.org:443\r\n"
21908 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021909 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421910 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21911 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21912 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21913 ssl_origin4.expected_send_client_cert = true;
21914 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021915 // The client sends the origin HTTP request, which results in another HTTP
21916 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421917 mock_writes4.emplace_back(
21918 "GET / HTTP/1.1\r\n"
21919 "Host: www.example.org\r\n"
21920 "Connection: keep-alive\r\n\r\n");
21921 mock_reads4.emplace_back(
21922 "HTTP/1.1 401 Unauthorized\r\n"
21923 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21924 "Connection: close\r\n"
21925 "Content-Length: 0\r\n\r\n");
21926 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21927 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021928 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21929 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421930
David Benjamin7ebab032019-04-30 21:51:3021931 // The client retries with credentials on a new connection, and the request
21932 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421933 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21934 ssl_proxy5.expected_send_client_cert = true;
21935 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21936 std::vector<MockWrite> mock_writes5;
21937 std::vector<MockRead> mock_reads5;
21938 mock_writes5.emplace_back(
21939 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21940 "Host: www.example.org:443\r\n"
21941 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021942 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421943 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21944 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21945 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21946 ssl_origin5.expected_send_client_cert = true;
21947 ssl_origin5.expected_client_cert = identity_origin->certificate();
21948 mock_writes5.emplace_back(
21949 "GET / HTTP/1.1\r\n"
21950 "Host: www.example.org\r\n"
21951 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021952 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421953 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21954 mock_reads5.emplace_back(
21955 "HTTP/1.1 200 OK\r\n"
21956 "Connection: close\r\n"
21957 "Content-Length: 0\r\n\r\n");
21958 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21959 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021960 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21961 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421962
David Benjaminbac8dff2019-08-07 01:30:4121963 // The client makes a second request. This needs yet another connection, but
21964 // all credentials are cached.
21965 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21966 ssl_proxy6.expected_send_client_cert = true;
21967 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21968 std::vector<MockWrite> mock_writes6;
21969 std::vector<MockRead> mock_reads6;
21970 mock_writes6.emplace_back(
21971 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21972 "Host: www.example.org:443\r\n"
21973 "Proxy-Connection: keep-alive\r\n"
21974 // Authenticate as proxyuser:proxypass.
21975 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21976 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21977 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21978 ssl_origin6.expected_send_client_cert = true;
21979 ssl_origin6.expected_client_cert = identity_origin->certificate();
21980 mock_writes6.emplace_back(
21981 "GET / HTTP/1.1\r\n"
21982 "Host: www.example.org\r\n"
21983 "Connection: keep-alive\r\n"
21984 // Authenticate as user:pass.
21985 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21986 mock_reads6.emplace_back(
21987 "HTTP/1.1 200 OK\r\n"
21988 "Connection: close\r\n"
21989 "Content-Length: 0\r\n\r\n");
21990 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21991 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21994
David Benjamin2eb827f2019-04-29 18:31:0421995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21996
21997 // Start the request.
21998 TestCompletionCallback callback;
21999 auto trans =
22000 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22001 int rv = callback.GetResult(
22002 trans->Start(&request, callback.callback(), NetLogWithSource()));
22003
22004 // Handle the proxy client certificate challenge.
22005 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22006 SSLCertRequestInfo* cert_request_info =
22007 trans->GetResponseInfo()->cert_request_info.get();
22008 ASSERT_TRUE(cert_request_info);
22009 EXPECT_TRUE(cert_request_info->is_proxy);
22010 EXPECT_EQ(cert_request_info->host_and_port,
22011 cert_request_info_proxy->host_and_port);
22012 rv = callback.GetResult(trans->RestartWithCertificate(
22013 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
22014 callback.callback()));
22015
22016 // Handle the proxy HTTP auth challenge.
22017 ASSERT_THAT(rv, IsOk());
22018 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
22019 EXPECT_TRUE(
22020 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
22021 rv = callback.GetResult(trans->RestartWithAuth(
22022 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
22023 callback.callback()));
22024
22025 // Handle the origin client certificate challenge.
22026 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22027 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
22028 ASSERT_TRUE(cert_request_info);
22029 EXPECT_FALSE(cert_request_info->is_proxy);
22030 EXPECT_EQ(cert_request_info->host_and_port,
22031 cert_request_info_origin->host_and_port);
22032 rv = callback.GetResult(trans->RestartWithCertificate(
22033 identity_origin->certificate(), identity_origin->ssl_private_key(),
22034 callback.callback()));
22035
22036 // Handle the origin HTTP auth challenge.
22037 ASSERT_THAT(rv, IsOk());
22038 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
22039 EXPECT_TRUE(
22040 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
22041 rv = callback.GetResult(trans->RestartWithAuth(
22042 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
22043 callback.callback()));
22044
22045 // The request completes.
22046 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3022047 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4122048
22049 // Make a second request. This time all credentials are cached.
22050 trans =
22051 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22052 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
22053 NetLogWithSource())),
22054 IsOk());
22055 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3022056}
22057
22058// Test the proxy requesting HTTP auth and the server requesting TLS client
22059// certificates. This is a regression test for https://crbug.com/946406.
22060TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
22061 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5622062 session_deps_.proxy_resolution_service =
22063 ConfiguredProxyResolutionService::CreateFixed(
22064 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin7ebab032019-04-30 21:51:3022065
22066 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
22067 cert_request_info_origin->host_and_port =
22068 HostPortPair("www.example.org", 443);
22069
22070 std::unique_ptr<FakeClientCertIdentity> identity_origin =
22071 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22072 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
22073 ASSERT_TRUE(identity_origin);
22074
22075 HttpRequestInfo request;
22076 request.method = "GET";
22077 request.url = GURL("https://www.example.org/");
22078 request.traffic_annotation =
22079 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22080
22081 // The client connects to the proxy. The handshake succeeds.
22082 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22083 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
22084 std::vector<MockWrite> mock_writes1;
22085 std::vector<MockRead> mock_reads1;
22086 mock_writes1.emplace_back(
22087 "CONNECT www.example.org:443 HTTP/1.1\r\n"
22088 "Host: www.example.org:443\r\n"
22089 "Proxy-Connection: keep-alive\r\n\r\n");
22090 mock_reads1.emplace_back(
22091 "HTTP/1.1 407 Proxy Authentication Required\r\n"
22092 "Content-Length: 0\r\n"
22093 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
22094 // The client retries with credentials, and the request finally succeeds.
22095 mock_writes1.emplace_back(
22096 "CONNECT www.example.org:443 HTTP/1.1\r\n"
22097 "Host: www.example.org:443\r\n"
22098 "Proxy-Connection: keep-alive\r\n"
22099 // Authenticate as proxyuser:proxypass.
22100 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
22101 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
22102 // The origin requests client certificates.
22103 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
22104 ssl_origin1.cert_request_info = cert_request_info_origin.get();
22105 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
22106 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22107 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22109
22110 // The client responds to the origin client certificate request on a new
22111 // connection.
22112 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22113 std::vector<MockWrite> mock_writes2;
22114 std::vector<MockRead> mock_reads2;
22115 mock_writes2.emplace_back(
22116 "CONNECT www.example.org:443 HTTP/1.1\r\n"
22117 "Host: www.example.org:443\r\n"
22118 "Proxy-Connection: keep-alive\r\n"
22119 // Authenticate as proxyuser:proxypass.
22120 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
22121 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
22122 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
22123 ssl_origin2.expected_send_client_cert = true;
22124 ssl_origin2.expected_client_cert = identity_origin->certificate();
22125 // The client sends the origin HTTP request, which succeeds.
22126 mock_writes2.emplace_back(
22127 "GET / HTTP/1.1\r\n"
22128 "Host: www.example.org\r\n"
22129 "Connection: keep-alive\r\n\r\n");
22130 mock_reads2.emplace_back(
22131 "HTTP/1.1 200 OK\r\n"
22132 "Content-Length: 0\r\n\r\n");
22133 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
22134 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22135 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22136 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
22137
22138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22139
22140 // Start the request.
22141 TestCompletionCallback callback;
22142 auto trans =
22143 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22144 int rv = callback.GetResult(
22145 trans->Start(&request, callback.callback(), NetLogWithSource()));
22146
22147 // Handle the proxy HTTP auth challenge.
22148 ASSERT_THAT(rv, IsOk());
22149 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
22150 EXPECT_TRUE(
22151 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
22152 rv = callback.GetResult(trans->RestartWithAuth(
22153 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
22154 callback.callback()));
22155
22156 // Handle the origin client certificate challenge.
22157 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22158 SSLCertRequestInfo* cert_request_info =
22159 trans->GetResponseInfo()->cert_request_info.get();
22160 ASSERT_TRUE(cert_request_info);
22161 EXPECT_FALSE(cert_request_info->is_proxy);
22162 EXPECT_EQ(cert_request_info->host_and_port,
22163 cert_request_info_origin->host_and_port);
22164 rv = callback.GetResult(trans->RestartWithCertificate(
22165 identity_origin->certificate(), identity_origin->ssl_private_key(),
22166 callback.callback()));
22167
22168 // The request completes.
22169 ASSERT_THAT(rv, IsOk());
22170 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0422171}
22172
David Benjamin6e673a82019-04-30 22:52:5822173// Test that socket reuse works with client certificates.
22174TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
22175 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22176 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
22177
22178 std::unique_ptr<FakeClientCertIdentity> identity =
22179 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22180 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22181 ASSERT_TRUE(identity);
22182
22183 HttpRequestInfo request1;
22184 request1.method = "GET";
22185 request1.url = GURL("https://www.example.org/a");
22186 request1.traffic_annotation =
22187 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22188
22189 HttpRequestInfo request2;
22190 request2.method = "GET";
22191 request2.url = GURL("https://www.example.org/b");
22192 request2.traffic_annotation =
22193 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22194
22195 // The first connection results in a client certificate request.
22196 StaticSocketDataProvider data1;
22197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22198 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
22199 ssl1.cert_request_info = cert_request_info.get();
22200 ssl1.expected_send_client_cert = false;
22201 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22202
22203 // The second connection succeeds and is usable for both requests.
22204 MockWrite mock_writes[] = {
22205 MockWrite("GET /a HTTP/1.1\r\n"
22206 "Host: www.example.org\r\n"
22207 "Connection: keep-alive\r\n\r\n"),
22208 MockWrite("GET /b HTTP/1.1\r\n"
22209 "Host: www.example.org\r\n"
22210 "Connection: keep-alive\r\n\r\n"),
22211 };
22212 MockRead mock_reads[] = {
22213 MockRead("HTTP/1.1 200 OK\r\n"
22214 "Content-Length: 0\r\n\r\n"),
22215 MockRead("HTTP/1.1 200 OK\r\n"
22216 "Content-Length: 0\r\n\r\n"),
22217 };
22218 StaticSocketDataProvider data2(mock_reads, mock_writes);
22219 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22220 SSLSocketDataProvider ssl2(ASYNC, OK);
22221 ssl2.expected_send_client_cert = true;
22222 ssl2.expected_client_cert = identity->certificate();
22223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22224
22225 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22226
22227 // Start the first request. It succeeds after providing client certificates.
22228 TestCompletionCallback callback;
22229 auto trans =
22230 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22231 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
22232 NetLogWithSource())),
22233 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22234
22235 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
22236 ASSERT_TRUE(info);
22237 EXPECT_FALSE(info->is_proxy);
22238 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
22239
22240 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
22241 identity->certificate(), identity->ssl_private_key(),
22242 callback.callback())),
22243 IsOk());
22244 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22245
22246 // Make the second request. It completes without requesting client
22247 // certificates.
22248 trans =
22249 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22250 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
22251 NetLogWithSource())),
22252 IsOk());
22253 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22254}
22255
Matt Menke166443c2019-05-24 18:45:5922256// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
22257// sequence with two different NetworkIsolationKeys, the first and last have the
22258// same key, the second a different one. Checks that the requests are
22259// partitioned across sockets as expected.
22260TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Matt Menke4807a9a2020-11-21 00:14:4122261 const SchemefulSite kSite1(GURL("http://origin1/"));
22262 const SchemefulSite kSite2(GURL("http://origin2/"));
22263 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
22264 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
Matt Menke166443c2019-05-24 18:45:5922265
22266 for (bool partition_connections : {false, true}) {
22267 SCOPED_TRACE(partition_connections);
22268
22269 base::test::ScopedFeatureList feature_list;
22270 if (partition_connections) {
22271 feature_list.InitAndEnableFeature(
22272 features::kPartitionConnectionsByNetworkIsolationKey);
22273 } else {
22274 feature_list.InitAndDisableFeature(
22275 features::kPartitionConnectionsByNetworkIsolationKey);
22276 }
22277
22278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22279
22280 // Reads and writes for the unpartitioned case, where only one socket is
22281 // used.
22282
22283 const MockWrite kUnpartitionedWrites[] = {
22284 MockWrite("GET /1 HTTP/1.1\r\n"
22285 "Host: foo.test\r\n"
22286 "Connection: keep-alive\r\n\r\n"),
22287 MockWrite("GET /2 HTTP/1.1\r\n"
22288 "Host: foo.test\r\n"
22289 "Connection: keep-alive\r\n\r\n"),
22290 MockWrite("GET /3 HTTP/1.1\r\n"
22291 "Host: foo.test\r\n"
22292 "Connection: keep-alive\r\n\r\n"),
22293 };
22294
22295 const MockRead kUnpartitionedReads[] = {
22296 MockRead("HTTP/1.1 200 OK\r\n"
22297 "Connection: keep-alive\r\n"
22298 "Content-Length: 1\r\n\r\n"
22299 "1"),
22300 MockRead("HTTP/1.1 200 OK\r\n"
22301 "Connection: keep-alive\r\n"
22302 "Content-Length: 1\r\n\r\n"
22303 "2"),
22304 MockRead("HTTP/1.1 200 OK\r\n"
22305 "Connection: keep-alive\r\n"
22306 "Content-Length: 1\r\n\r\n"
22307 "3"),
22308 };
22309
22310 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
22311 kUnpartitionedWrites);
22312
22313 // Reads and writes for the partitioned case, where two sockets are used.
22314
22315 const MockWrite kPartitionedWrites1[] = {
22316 MockWrite("GET /1 HTTP/1.1\r\n"
22317 "Host: foo.test\r\n"
22318 "Connection: keep-alive\r\n\r\n"),
22319 MockWrite("GET /3 HTTP/1.1\r\n"
22320 "Host: foo.test\r\n"
22321 "Connection: keep-alive\r\n\r\n"),
22322 };
22323
22324 const MockRead kPartitionedReads1[] = {
22325 MockRead("HTTP/1.1 200 OK\r\n"
22326 "Connection: keep-alive\r\n"
22327 "Content-Length: 1\r\n\r\n"
22328 "1"),
22329 MockRead("HTTP/1.1 200 OK\r\n"
22330 "Connection: keep-alive\r\n"
22331 "Content-Length: 1\r\n\r\n"
22332 "3"),
22333 };
22334
22335 const MockWrite kPartitionedWrites2[] = {
22336 MockWrite("GET /2 HTTP/1.1\r\n"
22337 "Host: foo.test\r\n"
22338 "Connection: keep-alive\r\n\r\n"),
22339 };
22340
22341 const MockRead kPartitionedReads2[] = {
22342 MockRead("HTTP/1.1 200 OK\r\n"
22343 "Connection: keep-alive\r\n"
22344 "Content-Length: 1\r\n\r\n"
22345 "2"),
22346 };
22347
22348 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
22349 kPartitionedWrites1);
22350 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
22351 kPartitionedWrites2);
22352
22353 if (partition_connections) {
22354 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22355 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22356 } else {
22357 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
22358 }
22359
22360 TestCompletionCallback callback;
22361 HttpRequestInfo request1;
22362 request1.method = "GET";
22363 request1.url = GURL("http://foo.test/1");
22364 request1.traffic_annotation =
22365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22366 request1.network_isolation_key = network_isolation_key1;
22367 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22368 session.get());
22369 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22370 EXPECT_THAT(callback.GetResult(rv), IsOk());
22371 std::string response_data1;
22372 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22373 EXPECT_EQ("1", response_data1);
22374 trans1.reset();
22375
22376 HttpRequestInfo request2;
22377 request2.method = "GET";
22378 request2.url = GURL("http://foo.test/2");
22379 request2.traffic_annotation =
22380 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22381 request2.network_isolation_key = network_isolation_key2;
22382 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22383 session.get());
22384 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22385 EXPECT_THAT(callback.GetResult(rv), IsOk());
22386 std::string response_data2;
22387 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22388 EXPECT_EQ("2", response_data2);
22389 trans2.reset();
22390
22391 HttpRequestInfo request3;
22392 request3.method = "GET";
22393 request3.url = GURL("http://foo.test/3");
22394 request3.traffic_annotation =
22395 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22396 request3.network_isolation_key = network_isolation_key1;
22397 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22398 session.get());
22399 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22400 EXPECT_THAT(callback.GetResult(rv), IsOk());
22401 std::string response_data3;
22402 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22403 EXPECT_EQ("3", response_data3);
22404 trans3.reset();
22405 }
22406}
22407
Matt Menkeae58eeb2019-05-24 21:09:5022408TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Matt Menke4807a9a2020-11-21 00:14:4122409 const SchemefulSite kSite1(GURL("http://origin1/"));
22410 const SchemefulSite kSite2(GURL("http://origin2/"));
22411 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
22412 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
Matt Menkeae58eeb2019-05-24 21:09:5022413
22414 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
22415 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
22416 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
22417 // the same way as the HTTP over H2 proxy case.
22418 for (bool use_proxy : {false, true}) {
22419 SCOPED_TRACE(use_proxy);
22420 if (use_proxy) {
22421 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622422 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkeae58eeb2019-05-24 21:09:5022423 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
22424 } else {
22425 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622426 ConfiguredProxyResolutionService::CreateDirect();
Matt Menkeae58eeb2019-05-24 21:09:5022427 }
22428 const char* url1 = nullptr;
22429 const char* url2 = nullptr;
22430 const char* url3 = nullptr;
22431 if (use_proxy) {
22432 url1 = "http://foo.test/1";
22433 url2 = "http://foo.test/2";
22434 url3 = "http://foo.test/3";
22435 } else {
22436 url1 = "https://foo.test/1";
22437 url2 = "https://foo.test/2";
22438 url3 = "https://foo.test/3";
22439 }
22440
22441 for (bool partition_connections : {false, true}) {
22442 SCOPED_TRACE(partition_connections);
22443
22444 base::test::ScopedFeatureList feature_list;
22445 if (partition_connections) {
22446 feature_list.InitAndEnableFeature(
22447 features::kPartitionConnectionsByNetworkIsolationKey);
22448 } else {
22449 feature_list.InitAndDisableFeature(
22450 features::kPartitionConnectionsByNetworkIsolationKey);
22451 }
22452
22453 std::unique_ptr<HttpNetworkSession> session(
22454 CreateSession(&session_deps_));
22455
22456 // Reads and writes for the unpartitioned case, where only one socket is
22457 // used.
22458
22459 SpdyTestUtil spdy_util;
22460 spdy::SpdySerializedFrame unpartitioned_req1(
22461 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
22462 spdy::SpdySerializedFrame unpartitioned_response1(
22463 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
22464 spdy::SpdySerializedFrame unpartitioned_body1(
22465 spdy_util.ConstructSpdyDataFrame(1, "1", true));
22466 spdy_util.UpdateWithStreamDestruction(1);
22467
22468 spdy::SpdySerializedFrame unpartitioned_req2(
22469 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
22470 spdy::SpdySerializedFrame unpartitioned_response2(
22471 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
22472 spdy::SpdySerializedFrame unpartitioned_body2(
22473 spdy_util.ConstructSpdyDataFrame(3, "2", true));
22474 spdy_util.UpdateWithStreamDestruction(3);
22475
22476 spdy::SpdySerializedFrame unpartitioned_req3(
22477 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
22478 spdy::SpdySerializedFrame unpartitioned_response3(
22479 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
22480 spdy::SpdySerializedFrame unpartitioned_body3(
22481 spdy_util.ConstructSpdyDataFrame(5, "3", true));
22482
22483 const MockWrite kUnpartitionedWrites[] = {
22484 CreateMockWrite(unpartitioned_req1, 0),
22485 CreateMockWrite(unpartitioned_req2, 3),
22486 CreateMockWrite(unpartitioned_req3, 6),
22487 };
22488
22489 const MockRead kUnpartitionedReads[] = {
22490 CreateMockRead(unpartitioned_response1, 1),
22491 CreateMockRead(unpartitioned_body1, 2),
22492 CreateMockRead(unpartitioned_response2, 4),
22493 CreateMockRead(unpartitioned_body2, 5),
22494 CreateMockRead(unpartitioned_response3, 7),
22495 CreateMockRead(unpartitioned_body3, 8),
22496 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
22497 };
22498
22499 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
22500 kUnpartitionedWrites);
22501
22502 // Reads and writes for the partitioned case, where two sockets are used.
22503
22504 SpdyTestUtil spdy_util2;
22505 spdy::SpdySerializedFrame partitioned_req1(
22506 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22507 spdy::SpdySerializedFrame partitioned_response1(
22508 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22509 spdy::SpdySerializedFrame partitioned_body1(
22510 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22511 spdy_util2.UpdateWithStreamDestruction(1);
22512
22513 spdy::SpdySerializedFrame partitioned_req3(
22514 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22515 spdy::SpdySerializedFrame partitioned_response3(
22516 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22517 spdy::SpdySerializedFrame partitioned_body3(
22518 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22519
22520 const MockWrite kPartitionedWrites1[] = {
22521 CreateMockWrite(partitioned_req1, 0),
22522 CreateMockWrite(partitioned_req3, 3),
22523 };
22524
22525 const MockRead kPartitionedReads1[] = {
22526 CreateMockRead(partitioned_response1, 1),
22527 CreateMockRead(partitioned_body1, 2),
22528 CreateMockRead(partitioned_response3, 4),
22529 CreateMockRead(partitioned_body3, 5),
22530 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22531 };
22532
22533 SpdyTestUtil spdy_util3;
22534 spdy::SpdySerializedFrame partitioned_req2(
22535 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22536 spdy::SpdySerializedFrame partitioned_response2(
22537 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22538 spdy::SpdySerializedFrame partitioned_body2(
22539 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22540
22541 const MockWrite kPartitionedWrites2[] = {
22542 CreateMockWrite(partitioned_req2, 0),
22543 };
22544
22545 const MockRead kPartitionedReads2[] = {
22546 CreateMockRead(partitioned_response2, 1),
22547 CreateMockRead(partitioned_body2, 2),
22548 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22549 };
22550
22551 SequencedSocketData partitioned_data1(kPartitionedReads1,
22552 kPartitionedWrites1);
22553 SequencedSocketData partitioned_data2(kPartitionedReads2,
22554 kPartitionedWrites2);
22555
22556 // No need to segment SSLDataProviders by whether or not partitioning is
22557 // enabled.
22558 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22559 ssl_data1.next_proto = kProtoHTTP2;
22560 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22561 ssl_data2.next_proto = kProtoHTTP2;
22562
22563 if (partition_connections) {
22564 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22566 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22567 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22568 } else {
22569 session_deps_.socket_factory->AddSocketDataProvider(
22570 &unpartitioned_data);
22571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22572 }
22573
22574 TestCompletionCallback callback;
22575 HttpRequestInfo request1;
22576 request1.method = "GET";
22577 request1.url = GURL(url1);
22578 request1.traffic_annotation =
22579 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22580 request1.network_isolation_key = network_isolation_key1;
22581 auto trans1 =
22582 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22583 int rv =
22584 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22585 EXPECT_THAT(callback.GetResult(rv), IsOk());
22586 std::string response_data1;
22587 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22588 EXPECT_EQ("1", response_data1);
22589 trans1.reset();
22590
22591 HttpRequestInfo request2;
22592 request2.method = "GET";
22593 request2.url = GURL(url2);
22594 request2.traffic_annotation =
22595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22596 request2.network_isolation_key = network_isolation_key2;
22597 auto trans2 =
22598 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22599 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22600 EXPECT_THAT(callback.GetResult(rv), IsOk());
22601 std::string response_data2;
22602 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22603 EXPECT_EQ("2", response_data2);
22604 trans2.reset();
22605
22606 HttpRequestInfo request3;
22607 request3.method = "GET";
22608 request3.url = GURL(url3);
22609 request3.traffic_annotation =
22610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22611 request3.network_isolation_key = network_isolation_key1;
22612 auto trans3 =
22613 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22614 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22615 EXPECT_THAT(callback.GetResult(rv), IsOk());
22616 std::string response_data3;
22617 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22618 EXPECT_EQ("3", response_data3);
22619 trans3.reset();
22620 }
22621 }
22622}
22623
Matt Menke7281f872019-06-25 19:29:2522624// Preconnect two sockets with different NetworkIsolationKeys when
22625// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22626// request and make sure the correct socket is used. Loops three times,
22627// expecting to use the first preconnect, second preconnect, and neither.
22628TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22629 base::test::ScopedFeatureList feature_list;
22630 feature_list.InitAndEnableFeature(
22631 features::kPartitionConnectionsByNetworkIsolationKey);
22632
22633 enum class TestCase {
22634 kUseFirstPreconnect,
22635 kUseSecondPreconnect,
22636 kDontUsePreconnect,
22637 };
22638
Matt Menke4807a9a2020-11-21 00:14:4122639 const SchemefulSite kSite1(GURL("http://origin1/"));
22640 const SchemefulSite kSite2(GURL("http://origin2/"));
22641 const SchemefulSite kSite3(GURL("http://origin3/"));
22642 NetworkIsolationKey preconnect1_isolation_key(kSite1, kSite1);
22643 NetworkIsolationKey preconnect2_isolation_key(kSite2, kSite2);
22644 NetworkIsolationKey not_preconnected_isolation_key(kSite3, kSite3);
Matt Menke7281f872019-06-25 19:29:2522645
22646 // Test that only preconnects with
22647 for (TestCase test_case :
22648 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22649 TestCase::kDontUsePreconnect}) {
22650 SpdySessionDependencies session_deps;
22651 // Make DNS lookups completely synchronously, so preconnects complete
22652 // immediately.
22653 session_deps.host_resolver->set_synchronous_mode(true);
22654
22655 const MockWrite kMockWrites[] = {
22656 MockWrite(ASYNC, 0,
22657 "GET / HTTP/1.1\r\n"
22658 "Host: www.foo.com\r\n"
22659 "Connection: keep-alive\r\n\r\n"),
22660 };
22661
22662 const MockRead kMockReads[] = {
22663 MockRead(ASYNC, 1,
22664 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22665 "hello"),
22666 };
22667
22668 // Used for the socket that will actually be used, which may or may not be
22669 // one of the preconnects
22670 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22671 kMockReads, kMockWrites);
22672
22673 // Used for the preconnects that won't actually be used.
22674 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22675 base::span<const MockRead>(),
22676 base::span<const MockWrite>());
22677 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22678 base::span<const MockRead>(),
22679 base::span<const MockWrite>());
22680
22681 NetworkIsolationKey network_isolation_key_for_request;
22682
22683 switch (test_case) {
22684 case TestCase::kUseFirstPreconnect:
22685 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22686 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22687 network_isolation_key_for_request = preconnect1_isolation_key;
22688 break;
22689 case TestCase::kUseSecondPreconnect:
22690 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22691 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22692 network_isolation_key_for_request = preconnect2_isolation_key;
22693 break;
22694 case TestCase::kDontUsePreconnect:
22695 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22696 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22697 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22698 network_isolation_key_for_request = not_preconnected_isolation_key;
22699 break;
22700 }
22701
22702 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22703
22704 // Preconnect sockets.
22705 HttpRequestInfo request;
22706 request.method = "GET";
22707 request.url = GURL("http://www.foo.com/");
22708 request.traffic_annotation =
22709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22710
22711 request.network_isolation_key = preconnect1_isolation_key;
22712 session->http_stream_factory()->PreconnectStreams(1, request);
22713
22714 request.network_isolation_key = preconnect2_isolation_key;
22715 session->http_stream_factory()->PreconnectStreams(1, request);
22716
22717 request.network_isolation_key = network_isolation_key_for_request;
22718
22719 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22720
22721 // Make the request.
22722 TestCompletionCallback callback;
22723
22724 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22725
22726 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22728
22729 rv = callback.WaitForResult();
22730 EXPECT_THAT(rv, IsOk());
22731
22732 const HttpResponseInfo* response = trans.GetResponseInfo();
22733 ASSERT_TRUE(response);
22734 ASSERT_TRUE(response->headers);
22735 EXPECT_EQ(200, response->headers->response_code());
22736
22737 std::string response_data;
22738 rv = ReadTransaction(&trans, &response_data);
22739 EXPECT_THAT(rv, IsOk());
22740 EXPECT_EQ("hello", response_data);
22741
22742 if (test_case != TestCase::kDontUsePreconnect) {
22743 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22744 } else {
22745 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22746 }
22747 }
22748}
22749
David Benjamin6f2da652019-06-26 23:36:3522750// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22751// cache is isolated.
22752TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22753 base::test::ScopedFeatureList feature_list;
22754 feature_list.InitWithFeatures(
22755 {features::kPartitionConnectionsByNetworkIsolationKey,
22756 features::kPartitionSSLSessionsByNetworkIsolationKey},
22757 {});
22758
Matt Menke4807a9a2020-11-21 00:14:4122759 const SchemefulSite kSite1(GURL("http://origin1/"));
22760 const SchemefulSite kSite2(GURL("http://origin2/"));
22761 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
22762 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
David Benjamin6f2da652019-06-26 23:36:3522763 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22764
22765 // The server always sends Connection: close, so each request goes over a
22766 // distinct socket.
22767
22768 const MockWrite kWrites1[] = {
22769 MockWrite("GET /1 HTTP/1.1\r\n"
22770 "Host: foo.test\r\n"
22771 "Connection: keep-alive\r\n\r\n")};
22772
22773 const MockRead kReads1[] = {
22774 MockRead("HTTP/1.1 200 OK\r\n"
22775 "Connection: close\r\n"
22776 "Content-Length: 1\r\n\r\n"
22777 "1")};
22778
22779 const MockWrite kWrites2[] = {
22780 MockWrite("GET /2 HTTP/1.1\r\n"
22781 "Host: foo.test\r\n"
22782 "Connection: keep-alive\r\n\r\n")};
22783
22784 const MockRead kReads2[] = {
22785 MockRead("HTTP/1.1 200 OK\r\n"
22786 "Connection: close\r\n"
22787 "Content-Length: 1\r\n\r\n"
22788 "2")};
22789
22790 const MockWrite kWrites3[] = {
22791 MockWrite("GET /3 HTTP/1.1\r\n"
22792 "Host: foo.test\r\n"
22793 "Connection: keep-alive\r\n\r\n")};
22794
22795 const MockRead kReads3[] = {
22796 MockRead("HTTP/1.1 200 OK\r\n"
22797 "Connection: close\r\n"
22798 "Content-Length: 1\r\n\r\n"
22799 "3")};
22800
22801 StaticSocketDataProvider data1(kReads1, kWrites1);
22802 StaticSocketDataProvider data2(kReads2, kWrites2);
22803 StaticSocketDataProvider data3(kReads3, kWrites3);
22804 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22805 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22806 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22807
22808 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22809 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22810 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22811 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22812 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22813 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22814 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22815 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22816 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22817 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22820
22821 TestCompletionCallback callback;
22822 HttpRequestInfo request1;
22823 request1.method = "GET";
22824 request1.url = GURL("https://foo.test/1");
22825 request1.traffic_annotation =
22826 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22827 request1.network_isolation_key = kNetworkIsolationKey1;
22828 auto trans1 =
22829 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22830 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22831 EXPECT_THAT(callback.GetResult(rv), IsOk());
22832 std::string response_data1;
22833 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22834 EXPECT_EQ("1", response_data1);
22835 trans1.reset();
22836
22837 HttpRequestInfo request2;
22838 request2.method = "GET";
22839 request2.url = GURL("https://foo.test/2");
22840 request2.traffic_annotation =
22841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22842 request2.network_isolation_key = kNetworkIsolationKey2;
22843 auto trans2 =
22844 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22845 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22846 EXPECT_THAT(callback.GetResult(rv), IsOk());
22847 std::string response_data2;
22848 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22849 EXPECT_EQ("2", response_data2);
22850 trans2.reset();
22851
22852 HttpRequestInfo request3;
22853 request3.method = "GET";
22854 request3.url = GURL("https://foo.test/3");
22855 request3.traffic_annotation =
22856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22857 request3.network_isolation_key = kNetworkIsolationKey1;
22858 auto trans3 =
22859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22860 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22861 EXPECT_THAT(callback.GetResult(rv), IsOk());
22862 std::string response_data3;
22863 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22864 EXPECT_EQ("3", response_data3);
22865 trans3.reset();
22866}
22867
22868// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22869// cache is isolated, for both origins and proxies.
22870TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22871 base::test::ScopedFeatureList feature_list;
22872 feature_list.InitWithFeatures(
22873 {features::kPartitionConnectionsByNetworkIsolationKey,
22874 features::kPartitionSSLSessionsByNetworkIsolationKey},
22875 {});
22876
Nicolas Arciniegad2013f92020-02-07 23:00:5622877 session_deps_.proxy_resolution_service =
22878 ConfiguredProxyResolutionService::CreateFixed(
22879 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin6f2da652019-06-26 23:36:3522880
Matt Menke4807a9a2020-11-21 00:14:4122881 const SchemefulSite kSite1(GURL("http://origin1/"));
22882 const SchemefulSite kSite2(GURL("http://origin2/"));
22883 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
22884 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
David Benjamin6f2da652019-06-26 23:36:3522885 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22886
22887 // Make both a tunneled and non-tunneled request.
22888 HttpRequestInfo request1;
22889 request1.method = "GET";
22890 request1.url = GURL("https://foo.test/1");
22891 request1.traffic_annotation =
22892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22893 request1.network_isolation_key = kNetworkIsolationKey1;
22894
22895 HttpRequestInfo request2;
22896 request2.method = "GET";
22897 request2.url = GURL("http://foo.test/2");
22898 request2.traffic_annotation =
22899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22900 request2.network_isolation_key = kNetworkIsolationKey2;
22901
22902 const MockWrite kWrites1[] = {
22903 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22904 "Host: foo.test:443\r\n"
22905 "Proxy-Connection: keep-alive\r\n\r\n"),
22906 MockWrite("GET /1 HTTP/1.1\r\n"
22907 "Host: foo.test\r\n"
22908 "Connection: keep-alive\r\n\r\n")};
22909
22910 const MockRead kReads1[] = {
22911 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22912 MockRead("HTTP/1.1 200 OK\r\n"
22913 "Connection: close\r\n"
22914 "Content-Length: 1\r\n\r\n"
22915 "1")};
22916
22917 const MockWrite kWrites2[] = {
22918 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22919 "Host: foo.test\r\n"
22920 "Proxy-Connection: keep-alive\r\n\r\n")};
22921
22922 const MockRead kReads2[] = {
22923 MockRead("HTTP/1.1 200 OK\r\n"
22924 "Connection: close\r\n"
22925 "Content-Length: 1\r\n\r\n"
22926 "2")};
22927
22928 StaticSocketDataProvider data1(kReads1, kWrites1);
22929 StaticSocketDataProvider data2(kReads2, kWrites2);
22930 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22931 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22932 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22933
22934 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22935 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22936 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22937 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22938 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22939 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22940 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22941 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22942 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22943 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22945 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22946
22947 TestCompletionCallback callback;
22948 auto trans1 =
22949 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22950 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22951 EXPECT_THAT(callback.GetResult(rv), IsOk());
22952 std::string response_data1;
22953 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22954 EXPECT_EQ("1", response_data1);
22955 trans1.reset();
22956
22957 auto trans2 =
22958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22959 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22960 EXPECT_THAT(callback.GetResult(rv), IsOk());
22961 std::string response_data2;
22962 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22963 EXPECT_EQ("2", response_data2);
22964 trans2.reset();
22965}
22966
David Benjaminef2f2a5a2019-07-16 19:21:3122967// Test that SSLConfig changes from SSLConfigService are picked up even when
22968// there are live sockets.
22969TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222970 SSLContextConfig ssl_context_config;
22971 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22972 auto ssl_config_service =
22973 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122974 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22975
22976 session_deps_.ssl_config_service = std::move(ssl_config_service);
22977
22978 // Make three requests. Between the second and third, the SSL config will
22979 // change.
22980 HttpRequestInfo request1;
22981 request1.method = "GET";
22982 request1.url = GURL("https://foo.test/1");
22983 request1.traffic_annotation =
22984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22985
22986 HttpRequestInfo request2;
22987 request2.method = "GET";
22988 request2.url = GURL("https://foo.test/2");
22989 request2.traffic_annotation =
22990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22991
22992 HttpRequestInfo request3;
22993 request3.method = "GET";
22994 request3.url = GURL("https://foo.test/3");
22995 request3.traffic_annotation =
22996 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22997
22998 const MockWrite kWrites1[] = {
22999 MockWrite("GET /1 HTTP/1.1\r\n"
23000 "Host: foo.test\r\n"
23001 "Connection: keep-alive\r\n\r\n"),
23002 MockWrite("GET /2 HTTP/1.1\r\n"
23003 "Host: foo.test\r\n"
23004 "Connection: keep-alive\r\n\r\n"),
23005 };
23006
23007 const MockRead kReads1[] = {
23008 MockRead("HTTP/1.1 200 OK\r\n"
23009 "Connection: keep-alive\r\n"
23010 "Content-Length: 1\r\n\r\n"
23011 "1"),
23012 MockRead("HTTP/1.1 200 OK\r\n"
23013 "Connection: keep-alive\r\n"
23014 "Content-Length: 1\r\n\r\n"
23015 "2"),
23016 };
23017
23018 // The third request goes on a different socket because the SSL config has
23019 // changed.
23020 const MockWrite kWrites2[] = {
23021 MockWrite("GET /3 HTTP/1.1\r\n"
23022 "Host: foo.test\r\n"
23023 "Connection: keep-alive\r\n\r\n")};
23024
23025 const MockRead kReads2[] = {
23026 MockRead("HTTP/1.1 200 OK\r\n"
23027 "Connection: keep-alive\r\n"
23028 "Content-Length: 1\r\n\r\n"
23029 "3")};
23030
23031 StaticSocketDataProvider data1(kReads1, kWrites1);
23032 StaticSocketDataProvider data2(kReads2, kWrites2);
23033 session_deps_.socket_factory->AddSocketDataProvider(&data1);
23034 session_deps_.socket_factory->AddSocketDataProvider(&data2);
23035
23036 SSLSocketDataProvider ssl1(ASYNC, OK);
23037 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
23038 SSLSocketDataProvider ssl2(ASYNC, OK);
23039 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
23040 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
23041 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
23042
23043 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23044
23045 TestCompletionCallback callback;
23046 auto trans1 =
23047 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23048 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
23049 EXPECT_THAT(callback.GetResult(rv), IsOk());
23050 std::string response_data1;
23051 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
23052 EXPECT_EQ("1", response_data1);
23053 trans1.reset();
23054
23055 auto trans2 =
23056 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23057 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
23058 EXPECT_THAT(callback.GetResult(rv), IsOk());
23059 std::string response_data2;
23060 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
23061 EXPECT_EQ("2", response_data2);
23062 trans2.reset();
23063
David Benjamin151ec6b2019-08-02 19:38:5223064 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
23065 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3123066
23067 auto trans3 =
23068 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23069 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
23070 EXPECT_THAT(callback.GetResult(rv), IsOk());
23071 std::string response_data3;
23072 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
23073 EXPECT_EQ("3", response_data3);
23074 trans3.reset();
23075}
23076
23077TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5223078 SSLContextConfig ssl_context_config;
23079 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
23080 auto ssl_config_service =
23081 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3123082 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
23083
23084 session_deps_.ssl_config_service = std::move(ssl_config_service);
23085
23086 HttpRequestInfo request;
23087 request.method = "GET";
23088 request.url = GURL("https://foo.test/1");
23089 request.traffic_annotation =
23090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23091
23092 // Make a socket which never connects.
23093 StaticSocketDataProvider data({}, {});
23094 session_deps_.socket_factory->AddSocketDataProvider(&data);
23095 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
23096 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
23097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
23098
23099 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23100
23101 TestCompletionCallback callback;
23102 auto trans =
23103 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23104 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
23105 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23106
David Benjamin151ec6b2019-08-02 19:38:5223107 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
23108 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3123109
23110 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
23111}
23112
David Benjaminbac8dff2019-08-07 01:30:4123113// Test that HttpNetworkTransaction correctly handles existing sockets when the
23114// server requests a client certificate post-handshake (via a TLS
23115// renegotiation). This is a regression test for https://crbug.com/829184.
23116TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
23117 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
23118 TRAFFIC_ANNOTATION_FOR_TESTS);
23119
23120 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
23121 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
23122
23123 std::unique_ptr<FakeClientCertIdentity> identity =
23124 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
23125 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
23126 ASSERT_TRUE(identity);
23127
23128 // This test will make several requests so that, when the client certificate
23129 // request comes in, we have a socket in use, an idle socket, and a socket for
23130 // an unrelated host.
23131 //
23132 // First, two long-lived requests which do not complete until after the client
23133 // certificate request. This arranges for sockets to be in use during the
23134 // request. They should not be interrupted.
23135 HttpRequestInfo request_long_lived;
23136 request_long_lived.method = "GET";
23137 request_long_lived.url = GURL("https://foo.test/long-lived");
23138 request_long_lived.traffic_annotation = kTrafficAnnotation;
23139
23140 HttpRequestInfo request_long_lived_bar;
23141 request_long_lived_bar.method = "GET";
23142 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
23143 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
23144
23145 // Next, make a request that needs client certificates.
23146 HttpRequestInfo request_auth;
23147 request_auth.method = "GET";
23148 request_auth.url = GURL("https://foo.test/auth");
23149 request_auth.traffic_annotation = kTrafficAnnotation;
23150
23151 // Before responding to the challenge, make a request to an unauthenticated
23152 // endpoint. This will result in an idle socket when the client certificate
23153 // challenge is resolved.
23154 HttpRequestInfo request_unauth;
23155 request_unauth.method = "GET";
23156 request_unauth.url = GURL("https://foo.test/unauth");
23157 request_unauth.traffic_annotation = kTrafficAnnotation;
23158
23159 // After all the preceding requests complete, end with two additional requests
23160 // to ensure pre-authentication foo.test sockets are not used and bar.test
23161 // sockets are unaffected.
23162 HttpRequestInfo request_post_auth;
23163 request_post_auth.method = "GET";
23164 request_post_auth.url = GURL("https://foo.test/post-auth");
23165 request_post_auth.traffic_annotation = kTrafficAnnotation;
23166
23167 HttpRequestInfo request_post_auth_bar;
23168 request_post_auth_bar.method = "GET";
23169 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
23170 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
23171
23172 // The sockets for /long-lived and /unauth complete their request but are
23173 // not allocated for /post-auth or /retry because SSL state has since changed.
23174 const MockWrite kLongLivedWrites[] = {
23175 MockWrite(ASYNC, 0,
23176 "GET /long-lived HTTP/1.1\r\n"
23177 "Host: foo.test\r\n"
23178 "Connection: keep-alive\r\n\r\n"),
23179 };
23180 const MockRead kLongLivedReads[] = {
23181 // Pause so /long-lived completes after the client presents client
23182 // certificates.
23183 MockRead(ASYNC, ERR_IO_PENDING, 1),
23184 MockRead(ASYNC, 2,
23185 "HTTP/1.1 200 OK\r\n"
23186 "Connection: keep-alive\r\n"
23187 "Content-Length: 10\r\n\r\n"
23188 "long-lived"),
23189 };
23190 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
23191 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
23192 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
23193 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
23194
23195 // Requests for bar.test should be unaffected by foo.test and get allocated
23196 // a single socket.
23197 const MockWrite kBarWrites[] = {
23198 MockWrite(ASYNC, 0,
23199 "GET /long-lived HTTP/1.1\r\n"
23200 "Host: bar.test\r\n"
23201 "Connection: keep-alive\r\n\r\n"),
23202 MockWrite(ASYNC, 3,
23203 "GET /post-auth HTTP/1.1\r\n"
23204 "Host: bar.test\r\n"
23205 "Connection: keep-alive\r\n\r\n"),
23206 };
23207 const MockRead kBarReads[] = {
23208 // Pause on /long-lived so it completes after foo.test's authentication.
23209 MockRead(ASYNC, ERR_IO_PENDING, 1),
23210 MockRead(ASYNC, 2,
23211 "HTTP/1.1 200 OK\r\n"
23212 "Connection: keep-alive\r\n"
23213 "Content-Length: 10\r\n\r\n"
23214 "long-lived"),
23215 MockRead(ASYNC, 4,
23216 "HTTP/1.1 200 OK\r\n"
23217 "Connection: keep-alive\r\n"
23218 "Content-Length: 9\r\n\r\n"
23219 "post-auth"),
23220 };
23221 SequencedSocketData data_bar(kBarReads, kBarWrites);
23222 SSLSocketDataProvider ssl_bar(ASYNC, OK);
23223 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
23224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
23225
23226 // Requesting /auth results in a post-handshake client certificate challenge.
23227 const MockWrite kAuthWrites[] = {
23228 MockWrite(ASYNC, 0,
23229 "GET /auth HTTP/1.1\r\n"
23230 "Host: foo.test\r\n"
23231 "Connection: keep-alive\r\n\r\n"),
23232 };
23233 const MockRead kAuthReads[] = {
23234 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
23235 };
23236 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
23237 SSLSocketDataProvider ssl_auth(ASYNC, OK);
23238 ssl_auth.cert_request_info = cert_request_info.get();
23239 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
23240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
23241
23242 // Requesting /unauth completes.
23243 const MockWrite kUnauthWrites[] = {
23244 MockWrite(ASYNC, 0,
23245 "GET /unauth HTTP/1.1\r\n"
23246 "Host: foo.test\r\n"
23247 "Connection: keep-alive\r\n\r\n"),
23248 };
23249 const MockRead kUnauthReads[] = {
23250 MockRead(ASYNC, 1,
23251 "HTTP/1.1 200 OK\r\n"
23252 "Connection: keep-alive\r\n"
23253 "Content-Length: 6\r\n\r\n"
23254 "unauth"),
23255 };
23256 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
23257 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
23258 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
23259 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
23260
23261 // When the client certificate is selected, /auth is retried on a new
23262 // connection. In particular, it should not be retried on |data_unauth|,
23263 // which would not honor the new client certificate configuration.
23264 const MockWrite kRetryWrites[] = {
23265 MockWrite(ASYNC, 0,
23266 "GET /auth HTTP/1.1\r\n"
23267 "Host: foo.test\r\n"
23268 "Connection: keep-alive\r\n\r\n"),
23269 };
23270 const MockRead kRetryReads[] = {
23271 MockRead(ASYNC, 1,
23272 "HTTP/1.1 200 OK\r\n"
23273 // Close the connection so we test that /post-auth is not
23274 // allocated to |data_unauth| or |data_long_lived|.
23275 "Connection: close\r\n"
23276 "Content-Length: 4\r\n\r\n"
23277 "auth"),
23278 };
23279 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
23280 SSLSocketDataProvider ssl_retry(ASYNC, OK);
23281 ssl_retry.expected_send_client_cert = true;
23282 ssl_retry.expected_client_cert = identity->certificate();
23283 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
23284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
23285
23286 // /post-auth gets its own socket.
23287 const MockWrite kPostAuthWrites[] = {
23288 MockWrite(ASYNC, 0,
23289 "GET /post-auth HTTP/1.1\r\n"
23290 "Host: foo.test\r\n"
23291 "Connection: keep-alive\r\n\r\n"),
23292 };
23293 const MockRead kPostAuthReads[] = {
23294 MockRead(ASYNC, 1,
23295 "HTTP/1.1 200 OK\r\n"
23296 "Connection: keep-alive\r\n"
23297 "Content-Length: 9\r\n\r\n"
23298 "post-auth"),
23299 };
23300 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
23301 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
23302 ssl_post_auth.expected_send_client_cert = true;
23303 ssl_post_auth.expected_client_cert = identity->certificate();
23304 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
23305 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
23306
23307 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23308
23309 // Start the two long-lived requests.
23310 TestCompletionCallback callback_long_lived;
23311 auto trans_long_lived =
23312 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23313 int rv = trans_long_lived->Start(
23314 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
23315 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23316 data_long_lived.RunUntilPaused();
23317
23318 TestCompletionCallback callback_long_lived_bar;
23319 auto trans_long_lived_bar =
23320 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23321 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
23322 callback_long_lived_bar.callback(),
23323 NetLogWithSource());
23324 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23325 data_bar.RunUntilPaused();
23326
23327 // Request /auth. This gives a client certificate challenge.
23328 TestCompletionCallback callback_auth;
23329 auto trans_auth =
23330 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23331 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
23332 NetLogWithSource());
23333 EXPECT_THAT(callback_auth.GetResult(rv),
23334 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
23335
23336 // Make an unauthenticated request. This completes.
23337 TestCompletionCallback callback_unauth;
23338 auto trans_unauth =
23339 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23340 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
23341 NetLogWithSource());
23342 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
23343 std::string response_unauth;
23344 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
23345 EXPECT_EQ("unauth", response_unauth);
23346 trans_unauth.reset();
23347
23348 // Complete the authenticated request.
23349 rv = trans_auth->RestartWithCertificate(identity->certificate(),
23350 identity->ssl_private_key(),
23351 callback_auth.callback());
23352 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
23353 std::string response_auth;
23354 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
23355 EXPECT_EQ("auth", response_auth);
23356 trans_auth.reset();
23357
23358 // Complete the long-lived requests.
23359 data_long_lived.Resume();
23360 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
23361 std::string response_long_lived;
23362 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
23363 IsOk());
23364 EXPECT_EQ("long-lived", response_long_lived);
23365 trans_long_lived.reset();
23366
23367 data_bar.Resume();
23368 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
23369 std::string response_long_lived_bar;
23370 EXPECT_THAT(
23371 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
23372 IsOk());
23373 EXPECT_EQ("long-lived", response_long_lived_bar);
23374 trans_long_lived_bar.reset();
23375
23376 // Run the post-authentication requests.
23377 TestCompletionCallback callback_post_auth;
23378 auto trans_post_auth =
23379 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23380 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
23381 NetLogWithSource());
23382 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
23383 std::string response_post_auth;
23384 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
23385 IsOk());
23386 EXPECT_EQ("post-auth", response_post_auth);
23387 trans_post_auth.reset();
23388
23389 TestCompletionCallback callback_post_auth_bar;
23390 auto trans_post_auth_bar =
23391 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23392 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
23393 callback_post_auth_bar.callback(),
23394 NetLogWithSource());
23395 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
23396 std::string response_post_auth_bar;
23397 EXPECT_THAT(
23398 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
23399 IsOk());
23400 EXPECT_EQ("post-auth", response_post_auth_bar);
23401 trans_post_auth_bar.reset();
23402}
23403
[email protected]89ceba9a2009-03-21 03:46:0623404} // namespace net