blob: a63c0c086dfa3c61e5735df3a9025071204cb275 [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
maksim.sisov0adf8592016-07-15 06:25:569393// Grab a socket, use it, and put it back into the pool. Then, make
9394// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019395TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569396 HttpRequestInfo request;
9397 request.method = "GET";
9398 request.url = GURL("http://www.example.org/");
9399 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109400 request.traffic_annotation =
9401 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569402
9403 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9404
bnc691fda62016-08-12 00:43:169405 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569406
9407 MockRead data_reads[] = {
9408 // A part of the response body is received with the response headers.
9409 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9410 // The rest of the response body is received in two parts.
9411 MockRead("lo"), MockRead(" world"),
9412 MockRead("junk"), // Should not be read!!
9413 MockRead(SYNCHRONOUS, OK),
9414 };
9415
Ryan Sleevib8d7ea02018-05-07 20:01:019416 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569417 session_deps_.socket_factory->AddSocketDataProvider(&data);
9418
9419 TestCompletionCallback callback;
9420
tfarina42834112016-09-22 13:38:209421 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569422 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9423
9424 EXPECT_THAT(callback.GetResult(rv), IsOk());
9425
bnc691fda62016-08-12 00:43:169426 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569427 ASSERT_TRUE(response);
9428 EXPECT_TRUE(response->headers);
9429 std::string status_line = response->headers->GetStatusLine();
9430 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9431
9432 // Make memory critical notification and ensure the transaction still has been
9433 // operating right.
9434 base::MemoryPressureListener::NotifyMemoryPressure(
9435 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9436 base::RunLoop().RunUntilIdle();
9437
9438 // Socket should not be flushed as long as it is not idle.
9439 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9440
9441 std::string response_data;
bnc691fda62016-08-12 00:43:169442 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569443 EXPECT_THAT(rv, IsOk());
9444 EXPECT_EQ("hello world", response_data);
9445
9446 // Empty the current queue. This is necessary because idle sockets are
9447 // added to the connection pool asynchronously with a PostTask.
9448 base::RunLoop().RunUntilIdle();
9449
9450 // We now check to make sure the socket was added back to the pool.
9451 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9452
9453 // Idle sockets should be flushed now.
9454 base::MemoryPressureListener::NotifyMemoryPressure(
9455 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9456 base::RunLoop().RunUntilIdle();
9457
9458 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9459}
9460
yucliu48f235d2018-01-11 00:59:559461// Disable idle socket closing on memory pressure.
9462// Grab a socket, use it, and put it back into the pool. Then, make
9463// low memory notification and ensure the socket pool is NOT flushed.
9464TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9465 HttpRequestInfo request;
9466 request.method = "GET";
9467 request.url = GURL("http://www.example.org/");
9468 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109469 request.traffic_annotation =
9470 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559471
9472 // Disable idle socket closing on memory pressure.
9473 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9474 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9475
9476 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9477
9478 MockRead data_reads[] = {
9479 // A part of the response body is received with the response headers.
9480 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9481 // The rest of the response body is received in two parts.
9482 MockRead("lo"), MockRead(" world"),
9483 MockRead("junk"), // Should not be read!!
9484 MockRead(SYNCHRONOUS, OK),
9485 };
9486
Ryan Sleevib8d7ea02018-05-07 20:01:019487 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559488 session_deps_.socket_factory->AddSocketDataProvider(&data);
9489
9490 TestCompletionCallback callback;
9491
9492 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9493 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9494
9495 EXPECT_THAT(callback.GetResult(rv), IsOk());
9496
9497 const HttpResponseInfo* response = trans.GetResponseInfo();
9498 ASSERT_TRUE(response);
9499 EXPECT_TRUE(response->headers);
9500 std::string status_line = response->headers->GetStatusLine();
9501 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9502
9503 // Make memory critical notification and ensure the transaction still has been
9504 // operating right.
9505 base::MemoryPressureListener::NotifyMemoryPressure(
9506 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9507 base::RunLoop().RunUntilIdle();
9508
9509 // Socket should not be flushed as long as it is not idle.
9510 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9511
9512 std::string response_data;
9513 rv = ReadTransaction(&trans, &response_data);
9514 EXPECT_THAT(rv, IsOk());
9515 EXPECT_EQ("hello world", response_data);
9516
9517 // Empty the current queue. This is necessary because idle sockets are
9518 // added to the connection pool asynchronously with a PostTask.
9519 base::RunLoop().RunUntilIdle();
9520
9521 // We now check to make sure the socket was added back to the pool.
9522 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9523
9524 // Idle sockets should NOT be flushed on moderate memory pressure.
9525 base::MemoryPressureListener::NotifyMemoryPressure(
9526 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9527 base::RunLoop().RunUntilIdle();
9528
9529 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9530
9531 // Idle sockets should NOT be flushed on critical memory pressure.
9532 base::MemoryPressureListener::NotifyMemoryPressure(
9533 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9534 base::RunLoop().RunUntilIdle();
9535
9536 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9537}
9538
maksim.sisov0adf8592016-07-15 06:25:569539// Grab an SSL socket, use it, and put it back into the pool. Then, make
9540// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019541TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569542 HttpRequestInfo request;
9543 request.method = "GET";
9544 request.url = GURL("https://www.example.org/");
9545 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109546 request.traffic_annotation =
9547 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569548
9549 MockWrite data_writes[] = {
9550 MockWrite("GET / HTTP/1.1\r\n"
9551 "Host: www.example.org\r\n"
9552 "Connection: keep-alive\r\n\r\n"),
9553 };
9554
9555 MockRead data_reads[] = {
9556 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9557 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9558
9559 SSLSocketDataProvider ssl(ASYNC, OK);
9560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9561
Ryan Sleevib8d7ea02018-05-07 20:01:019562 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569563 session_deps_.socket_factory->AddSocketDataProvider(&data);
9564
9565 TestCompletionCallback callback;
9566
9567 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169568 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569569
Matt Menke9d5e2c92019-02-05 01:42:239570 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209571 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569572
9573 EXPECT_THAT(callback.GetResult(rv), IsOk());
9574
bnc691fda62016-08-12 00:43:169575 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569576 ASSERT_TRUE(response);
9577 ASSERT_TRUE(response->headers);
9578 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9579
9580 // Make memory critical notification and ensure the transaction still has been
9581 // operating right.
9582 base::MemoryPressureListener::NotifyMemoryPressure(
9583 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9584 base::RunLoop().RunUntilIdle();
9585
Matt Menke9d5e2c92019-02-05 01:42:239586 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569587
9588 std::string response_data;
bnc691fda62016-08-12 00:43:169589 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569590 EXPECT_THAT(rv, IsOk());
9591 EXPECT_EQ("hello world", response_data);
9592
9593 // Empty the current queue. This is necessary because idle sockets are
9594 // added to the connection pool asynchronously with a PostTask.
9595 base::RunLoop().RunUntilIdle();
9596
9597 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239598 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569599
9600 // Make memory notification once again and ensure idle socket is closed.
9601 base::MemoryPressureListener::NotifyMemoryPressure(
9602 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9603 base::RunLoop().RunUntilIdle();
9604
Matt Menke9d5e2c92019-02-05 01:42:239605 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569606}
9607
[email protected]b4404c02009-04-10 16:38:529608// Make sure that we recycle a socket after a zero-length response.
9609// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019610TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429611 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529612 request.method = "GET";
bncce36dca22015-04-21 22:11:239613 request.url = GURL(
9614 "http://www.example.org/csi?v=3&s=web&action=&"
9615 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9616 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9617 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:109618 request.traffic_annotation =
9619 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529620
danakj1fd259a02016-04-16 03:17:099621 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279622
[email protected]b4404c02009-04-10 16:38:529623 MockRead data_reads[] = {
9624 MockRead("HTTP/1.1 204 No Content\r\n"
9625 "Content-Length: 0\r\n"
9626 "Content-Type: text/html\r\n\r\n"),
9627 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069628 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529629 };
9630
Ryan Sleevib8d7ea02018-05-07 20:01:019631 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079632 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529633
mmenkecc2298e2015-12-07 18:20:189634 // Transaction must be created after the MockReads, so it's destroyed before
9635 // them.
bnc691fda62016-08-12 00:43:169636 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189637
[email protected]49639fa2011-12-20 23:22:419638 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529639
tfarina42834112016-09-22 13:38:209640 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529642
9643 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019644 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529645
bnc691fda62016-08-12 00:43:169646 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529647 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529648
wezca1070932016-05-26 20:30:529649 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529650 std::string status_line = response->headers->GetStatusLine();
9651 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9652
[email protected]90499482013-06-01 00:39:509653 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529654
9655 std::string response_data;
bnc691fda62016-08-12 00:43:169656 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019657 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529658 EXPECT_EQ("", response_data);
9659
9660 // Empty the current queue. This is necessary because idle sockets are
9661 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559662 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529663
9664 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509665 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529666}
9667
bncd16676a2016-07-20 16:23:019668TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099669 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229670 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199671 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229672 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279673
[email protected]1c773ea12009-04-28 19:58:429674 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519675 // Transaction 1: a GET request that succeeds. The socket is recycled
9676 // after use.
9677 request[0].method = "GET";
9678 request[0].url = GURL("http://www.google.com/");
9679 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109680 request[0].traffic_annotation =
9681 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519682 // Transaction 2: a POST request. Reuses the socket kept alive from
9683 // transaction 1. The first attempts fails when writing the POST data.
9684 // This causes the transaction to retry with a new socket. The second
9685 // attempt succeeds.
9686 request[1].method = "POST";
9687 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279688 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519689 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109690 request[1].traffic_annotation =
9691 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519692
danakj1fd259a02016-04-16 03:17:099693 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519694
9695 // The first socket is used for transaction 1 and the first attempt of
9696 // transaction 2.
9697
9698 // The response of transaction 1.
9699 MockRead data_reads1[] = {
9700 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9701 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069702 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519703 };
9704 // The mock write results of transaction 1 and the first attempt of
9705 // transaction 2.
9706 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069707 MockWrite(SYNCHRONOUS, 64), // GET
9708 MockWrite(SYNCHRONOUS, 93), // POST
9709 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519710 };
Ryan Sleevib8d7ea02018-05-07 20:01:019711 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519712
9713 // The second socket is used for the second attempt of transaction 2.
9714
9715 // The response of transaction 2.
9716 MockRead data_reads2[] = {
9717 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9718 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069719 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519720 };
9721 // The mock write results of the second attempt of transaction 2.
9722 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069723 MockWrite(SYNCHRONOUS, 93), // POST
9724 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519725 };
Ryan Sleevib8d7ea02018-05-07 20:01:019726 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519727
[email protected]bb88e1d32013-05-03 23:11:079728 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9729 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519730
thestig9d3bb0c2015-01-24 00:49:519731 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519732 "hello world", "welcome"
9733 };
9734
9735 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169736 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519737
[email protected]49639fa2011-12-20 23:22:419738 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519739
tfarina42834112016-09-22 13:38:209740 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019741 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519742
9743 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019744 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519745
bnc691fda62016-08-12 00:43:169746 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529747 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519748
wezca1070932016-05-26 20:30:529749 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519750 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9751
9752 std::string response_data;
bnc691fda62016-08-12 00:43:169753 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019754 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519755 EXPECT_EQ(kExpectedResponseData[i], response_data);
9756 }
9757}
[email protected]f9ee6b52008-11-08 06:46:239758
9759// Test the request-challenge-retry sequence for basic auth when there is
9760// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169761// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019762TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429763 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239764 request.method = "GET";
bncce36dca22015-04-21 22:11:239765 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419766 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109767 request.traffic_annotation =
9768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299769
danakj1fd259a02016-04-16 03:17:099770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169771 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279772
[email protected]a97cca42009-08-14 01:00:299773 // The password contains an escaped character -- for this test to pass it
9774 // will need to be unescaped by HttpNetworkTransaction.
9775 EXPECT_EQ("b%40r", request.url.password());
9776
[email protected]f9ee6b52008-11-08 06:46:239777 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239778 MockWrite(
9779 "GET / HTTP/1.1\r\n"
9780 "Host: www.example.org\r\n"
9781 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239782 };
9783
9784 MockRead data_reads1[] = {
9785 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9786 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9787 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069788 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239789 };
9790
[email protected]2262e3a2012-05-22 16:08:169791 // After the challenge above, the transaction will be restarted using the
9792 // identity from the url (foo, b@r) to answer the challenge.
9793 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239794 MockWrite(
9795 "GET / HTTP/1.1\r\n"
9796 "Host: www.example.org\r\n"
9797 "Connection: keep-alive\r\n"
9798 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169799 };
9800
9801 MockRead data_reads2[] = {
9802 MockRead("HTTP/1.0 200 OK\r\n"),
9803 MockRead("Content-Length: 100\r\n\r\n"),
9804 MockRead(SYNCHRONOUS, OK),
9805 };
9806
Ryan Sleevib8d7ea02018-05-07 20:01:019807 StaticSocketDataProvider data1(data_reads1, data_writes1);
9808 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239811
[email protected]49639fa2011-12-20 23:22:419812 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209813 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019814 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239815 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019816 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169817 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169818
9819 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169820 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019821 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169822 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019823 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169824 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229825
bnc691fda62016-08-12 00:43:169826 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529827 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169828
9829 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589830 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169831
9832 EXPECT_EQ(100, response->headers->GetContentLength());
9833
9834 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559835 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169836}
9837
9838// Test the request-challenge-retry sequence for basic auth when there is an
9839// incorrect identity in the URL. The identity from the URL should be used only
9840// once.
bncd16676a2016-07-20 16:23:019841TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169842 HttpRequestInfo request;
9843 request.method = "GET";
9844 // Note: the URL has a username:password in it. The password "baz" is
9845 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239846 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169847
9848 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109849 request.traffic_annotation =
9850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169851
danakj1fd259a02016-04-16 03:17:099852 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169853 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169854
9855 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239856 MockWrite(
9857 "GET / HTTP/1.1\r\n"
9858 "Host: www.example.org\r\n"
9859 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169860 };
9861
9862 MockRead data_reads1[] = {
9863 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9864 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9865 MockRead("Content-Length: 10\r\n\r\n"),
9866 MockRead(SYNCHRONOUS, ERR_FAILED),
9867 };
9868
9869 // After the challenge above, the transaction will be restarted using the
9870 // identity from the url (foo, baz) to answer the challenge.
9871 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239872 MockWrite(
9873 "GET / HTTP/1.1\r\n"
9874 "Host: www.example.org\r\n"
9875 "Connection: keep-alive\r\n"
9876 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169877 };
9878
9879 MockRead data_reads2[] = {
9880 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9881 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9882 MockRead("Content-Length: 10\r\n\r\n"),
9883 MockRead(SYNCHRONOUS, ERR_FAILED),
9884 };
9885
9886 // After the challenge above, the transaction will be restarted using the
9887 // identity supplied by the user (foo, bar) to answer the challenge.
9888 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239889 MockWrite(
9890 "GET / HTTP/1.1\r\n"
9891 "Host: www.example.org\r\n"
9892 "Connection: keep-alive\r\n"
9893 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169894 };
9895
9896 MockRead data_reads3[] = {
9897 MockRead("HTTP/1.0 200 OK\r\n"),
9898 MockRead("Content-Length: 100\r\n\r\n"),
9899 MockRead(SYNCHRONOUS, OK),
9900 };
9901
Ryan Sleevib8d7ea02018-05-07 20:01:019902 StaticSocketDataProvider data1(data_reads1, data_writes1);
9903 StaticSocketDataProvider data2(data_reads2, data_writes2);
9904 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079905 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9906 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9907 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169908
9909 TestCompletionCallback callback1;
9910
tfarina42834112016-09-22 13:38:209911 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169913
9914 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019915 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169916
bnc691fda62016-08-12 00:43:169917 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169918 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]2262e3a2012-05-22 16:08:169924
bnc691fda62016-08-12 00:43:169925 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529926 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589927 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169928
9929 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169930 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169932 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019933 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169934 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169935
bnc691fda62016-08-12 00:43:169936 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529937 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169938
9939 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589940 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169941
9942 EXPECT_EQ(100, response->headers->GetContentLength());
9943
[email protected]ea9dc9a2009-09-05 00:43:329944 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559945 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329946}
9947
[email protected]2217aa22013-10-11 03:03:549948
9949// Test the request-challenge-retry sequence for basic auth when there is a
9950// correct identity in the URL, but its use is being suppressed. The identity
9951// from the URL should never be used.
bncd16676a2016-07-20 16:23:019952TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549953 HttpRequestInfo request;
9954 request.method = "GET";
bncce36dca22015-04-21 22:11:239955 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549956 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:109957 request.traffic_annotation =
9958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549959
danakj1fd259a02016-04-16 03:17:099960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169961 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549962
9963 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239964 MockWrite(
9965 "GET / HTTP/1.1\r\n"
9966 "Host: www.example.org\r\n"
9967 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549968 };
9969
9970 MockRead data_reads1[] = {
9971 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9972 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9973 MockRead("Content-Length: 10\r\n\r\n"),
9974 MockRead(SYNCHRONOUS, ERR_FAILED),
9975 };
9976
9977 // After the challenge above, the transaction will be restarted using the
9978 // identity supplied by the user, not the one in the URL, to answer the
9979 // challenge.
9980 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239981 MockWrite(
9982 "GET / HTTP/1.1\r\n"
9983 "Host: www.example.org\r\n"
9984 "Connection: keep-alive\r\n"
9985 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549986 };
9987
9988 MockRead data_reads3[] = {
9989 MockRead("HTTP/1.0 200 OK\r\n"),
9990 MockRead("Content-Length: 100\r\n\r\n"),
9991 MockRead(SYNCHRONOUS, OK),
9992 };
9993
Ryan Sleevib8d7ea02018-05-07 20:01:019994 StaticSocketDataProvider data1(data_reads1, data_writes1);
9995 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549996 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9997 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9998
9999 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2010000 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110001 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410002 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110003 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610004 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410005
bnc691fda62016-08-12 00:43:1610006 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210007 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810008 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:5410009
10010 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1610011 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:0110012 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410013 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110014 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610015 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410016
bnc691fda62016-08-12 00:43:1610017 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210018 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:5410019
10020 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:5810021 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:5410022 EXPECT_EQ(100, response->headers->GetContentLength());
10023
10024 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:5510025 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:5410026}
10027
[email protected]f9ee6b52008-11-08 06:46:2310028// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:0110029TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:0910030 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:2310031
10032 // Transaction 1: authenticate (foo, bar) on MyRealm1
10033 {
[email protected]1c773ea12009-04-28 19:58:4210034 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310035 request.method = "GET";
bncce36dca22015-04-21 22:11:2310036 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010037 request.traffic_annotation =
10038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310039
bnc691fda62016-08-12 00:43:1610040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710041
[email protected]f9ee6b52008-11-08 06:46:2310042 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310043 MockWrite(
10044 "GET /x/y/z HTTP/1.1\r\n"
10045 "Host: www.example.org\r\n"
10046 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310047 };
10048
10049 MockRead data_reads1[] = {
10050 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10051 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10052 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610053 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310054 };
10055
10056 // Resend with authorization (username=foo, password=bar)
10057 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310058 MockWrite(
10059 "GET /x/y/z HTTP/1.1\r\n"
10060 "Host: www.example.org\r\n"
10061 "Connection: keep-alive\r\n"
10062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310063 };
10064
10065 // Sever accepts the authorization.
10066 MockRead data_reads2[] = {
10067 MockRead("HTTP/1.0 200 OK\r\n"),
10068 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610069 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310070 };
10071
Ryan Sleevib8d7ea02018-05-07 20:01:0110072 StaticSocketDataProvider data1(data_reads1, data_writes1);
10073 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710074 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10075 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310076
[email protected]49639fa2011-12-20 23:22:4110077 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310078
tfarina42834112016-09-22 13:38:2010079 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110080 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310081
10082 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110083 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310084
bnc691fda62016-08-12 00:43:1610085 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210086 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810087 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310088
[email protected]49639fa2011-12-20 23:22:4110089 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310090
bnc691fda62016-08-12 00:43:1610091 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10092 callback2.callback());
robpercival214763f2016-07-01 23:27:0110093 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310094
10095 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110096 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310097
bnc691fda62016-08-12 00:43:1610098 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210099 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810100 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310101 EXPECT_EQ(100, response->headers->GetContentLength());
10102 }
10103
10104 // ------------------------------------------------------------------------
10105
10106 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
10107 {
[email protected]1c773ea12009-04-28 19:58:4210108 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310109 request.method = "GET";
10110 // Note that Transaction 1 was at /x/y/z, so this is in the same
10111 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:2310112 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010113 request.traffic_annotation =
10114 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310115
bnc691fda62016-08-12 00:43:1610116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710117
[email protected]f9ee6b52008-11-08 06:46:2310118 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310119 MockWrite(
10120 "GET /x/y/a/b HTTP/1.1\r\n"
10121 "Host: www.example.org\r\n"
10122 "Connection: keep-alive\r\n"
10123 // Send preemptive authorization for MyRealm1
10124 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310125 };
10126
10127 // The server didn't like the preemptive authorization, and
10128 // challenges us for a different realm (MyRealm2).
10129 MockRead data_reads1[] = {
10130 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10131 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
10132 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610133 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310134 };
10135
10136 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
10137 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310138 MockWrite(
10139 "GET /x/y/a/b HTTP/1.1\r\n"
10140 "Host: www.example.org\r\n"
10141 "Connection: keep-alive\r\n"
10142 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310143 };
10144
10145 // Sever accepts the authorization.
10146 MockRead data_reads2[] = {
10147 MockRead("HTTP/1.0 200 OK\r\n"),
10148 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610149 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310150 };
10151
Ryan Sleevib8d7ea02018-05-07 20:01:0110152 StaticSocketDataProvider data1(data_reads1, data_writes1);
10153 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710154 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10155 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310156
[email protected]49639fa2011-12-20 23:22:4110157 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310158
tfarina42834112016-09-22 13:38:2010159 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110160 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310161
10162 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110163 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310164
bnc691fda62016-08-12 00:43:1610165 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210166 ASSERT_TRUE(response);
10167 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:0410168 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:4310169 EXPECT_EQ("http://www.example.org",
10170 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0410171 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:1910172 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:2310173
[email protected]49639fa2011-12-20 23:22:4110174 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310175
bnc691fda62016-08-12 00:43:1610176 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
10177 callback2.callback());
robpercival214763f2016-07-01 23:27:0110178 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310179
10180 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110181 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310182
bnc691fda62016-08-12 00:43:1610183 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210184 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810185 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310186 EXPECT_EQ(100, response->headers->GetContentLength());
10187 }
10188
10189 // ------------------------------------------------------------------------
10190
10191 // Transaction 3: Resend a request in MyRealm's protection space --
10192 // succeed with preemptive authorization.
10193 {
[email protected]1c773ea12009-04-28 19:58:4210194 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310195 request.method = "GET";
bncce36dca22015-04-21 22:11:2310196 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:1010197 request.traffic_annotation =
10198 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310199
bnc691fda62016-08-12 00:43:1610200 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710201
[email protected]f9ee6b52008-11-08 06:46:2310202 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310203 MockWrite(
10204 "GET /x/y/z2 HTTP/1.1\r\n"
10205 "Host: www.example.org\r\n"
10206 "Connection: keep-alive\r\n"
10207 // The authorization for MyRealm1 gets sent preemptively
10208 // (since the url is in the same protection space)
10209 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310210 };
10211
10212 // Sever accepts the preemptive authorization
10213 MockRead data_reads1[] = {
10214 MockRead("HTTP/1.0 200 OK\r\n"),
10215 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610216 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310217 };
10218
Ryan Sleevib8d7ea02018-05-07 20:01:0110219 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710220 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:2310221
[email protected]49639fa2011-12-20 23:22:4110222 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310223
tfarina42834112016-09-22 13:38:2010224 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110225 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310226
10227 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110228 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310229
bnc691fda62016-08-12 00:43:1610230 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210231 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:2310232
Emily Starkf2c9bbd2019-04-09 17:08:5810233 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310234 EXPECT_EQ(100, response->headers->GetContentLength());
10235 }
10236
10237 // ------------------------------------------------------------------------
10238
10239 // Transaction 4: request another URL in MyRealm (however the
10240 // url is not known to belong to the protection space, so no pre-auth).
10241 {
[email protected]1c773ea12009-04-28 19:58:4210242 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310243 request.method = "GET";
bncce36dca22015-04-21 22:11:2310244 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:1010245 request.traffic_annotation =
10246 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310247
bnc691fda62016-08-12 00:43:1610248 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710249
[email protected]f9ee6b52008-11-08 06:46:2310250 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310251 MockWrite(
10252 "GET /x/1 HTTP/1.1\r\n"
10253 "Host: www.example.org\r\n"
10254 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310255 };
10256
10257 MockRead data_reads1[] = {
10258 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10259 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10260 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610261 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310262 };
10263
10264 // Resend with authorization from MyRealm's cache.
10265 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310266 MockWrite(
10267 "GET /x/1 HTTP/1.1\r\n"
10268 "Host: www.example.org\r\n"
10269 "Connection: keep-alive\r\n"
10270 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310271 };
10272
10273 // Sever accepts the authorization.
10274 MockRead data_reads2[] = {
10275 MockRead("HTTP/1.0 200 OK\r\n"),
10276 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610277 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310278 };
10279
Ryan Sleevib8d7ea02018-05-07 20:01:0110280 StaticSocketDataProvider data1(data_reads1, data_writes1);
10281 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710282 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10283 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310284
[email protected]49639fa2011-12-20 23:22:4110285 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310286
tfarina42834112016-09-22 13:38:2010287 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110288 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310289
10290 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110291 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310292
bnc691fda62016-08-12 00:43:1610293 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110294 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610295 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110296 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210297 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110298 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610299 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210300
bnc691fda62016-08-12 00:43:1610301 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210302 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810303 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310304 EXPECT_EQ(100, response->headers->GetContentLength());
10305 }
10306
10307 // ------------------------------------------------------------------------
10308
10309 // Transaction 5: request a URL in MyRealm, but the server rejects the
10310 // cached identity. Should invalidate and re-prompt.
10311 {
[email protected]1c773ea12009-04-28 19:58:4210312 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310313 request.method = "GET";
bncce36dca22015-04-21 22:11:2310314 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:1010315 request.traffic_annotation =
10316 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310317
bnc691fda62016-08-12 00:43:1610318 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710319
[email protected]f9ee6b52008-11-08 06:46:2310320 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310321 MockWrite(
10322 "GET /p/q/t HTTP/1.1\r\n"
10323 "Host: www.example.org\r\n"
10324 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310325 };
10326
10327 MockRead data_reads1[] = {
10328 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10329 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10330 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610331 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310332 };
10333
10334 // Resend with authorization from cache for MyRealm.
10335 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310336 MockWrite(
10337 "GET /p/q/t HTTP/1.1\r\n"
10338 "Host: www.example.org\r\n"
10339 "Connection: keep-alive\r\n"
10340 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310341 };
10342
10343 // Sever rejects the authorization.
10344 MockRead data_reads2[] = {
10345 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10346 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10347 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610348 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310349 };
10350
10351 // At this point we should prompt for new credentials for MyRealm.
10352 // Restart with username=foo3, password=foo4.
10353 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310354 MockWrite(
10355 "GET /p/q/t HTTP/1.1\r\n"
10356 "Host: www.example.org\r\n"
10357 "Connection: keep-alive\r\n"
10358 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310359 };
10360
10361 // Sever accepts the authorization.
10362 MockRead data_reads3[] = {
10363 MockRead("HTTP/1.0 200 OK\r\n"),
10364 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610365 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310366 };
10367
Ryan Sleevib8d7ea02018-05-07 20:01:0110368 StaticSocketDataProvider data1(data_reads1, data_writes1);
10369 StaticSocketDataProvider data2(data_reads2, data_writes2);
10370 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710371 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10372 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10373 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:2310374
[email protected]49639fa2011-12-20 23:22:4110375 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310376
tfarina42834112016-09-22 13:38:2010377 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310379
10380 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110381 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310382
bnc691fda62016-08-12 00:43:1610383 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110384 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610385 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110386 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210387 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110388 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610389 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210390
bnc691fda62016-08-12 00:43:1610391 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210392 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810393 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310394
[email protected]49639fa2011-12-20 23:22:4110395 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:2310396
bnc691fda62016-08-12 00:43:1610397 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
10398 callback3.callback());
robpercival214763f2016-07-01 23:27:0110399 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310400
[email protected]0757e7702009-03-27 04:00:2210401 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110402 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310403
bnc691fda62016-08-12 00:43:1610404 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210405 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810406 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310407 EXPECT_EQ(100, response->headers->GetContentLength());
10408 }
10409}
[email protected]89ceba9a2009-03-21 03:46:0610410
[email protected]3c32c5f2010-05-18 15:18:1210411// Tests that nonce count increments when multiple auth attempts
10412// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110413TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410414 HttpAuthHandlerDigest::Factory* digest_factory =
10415 new HttpAuthHandlerDigest::Factory();
10416 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10417 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10418 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710419 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910420 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210421
10422 // Transaction 1: authenticate (foo, bar) on MyRealm1
10423 {
[email protected]3c32c5f2010-05-18 15:18:1210424 HttpRequestInfo request;
10425 request.method = "GET";
bncce36dca22015-04-21 22:11:2310426 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010427 request.traffic_annotation =
10428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210429
bnc691fda62016-08-12 00:43:1610430 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710431
[email protected]3c32c5f2010-05-18 15:18:1210432 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310433 MockWrite(
10434 "GET /x/y/z HTTP/1.1\r\n"
10435 "Host: www.example.org\r\n"
10436 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210437 };
10438
10439 MockRead data_reads1[] = {
10440 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10441 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10442 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610443 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210444 };
10445
10446 // Resend with authorization (username=foo, password=bar)
10447 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310448 MockWrite(
10449 "GET /x/y/z HTTP/1.1\r\n"
10450 "Host: www.example.org\r\n"
10451 "Connection: keep-alive\r\n"
10452 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10453 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10454 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10455 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210456 };
10457
10458 // Sever accepts the authorization.
10459 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810460 MockRead("HTTP/1.0 200 OK\r\n"),
10461 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210462 };
10463
Ryan Sleevib8d7ea02018-05-07 20:01:0110464 StaticSocketDataProvider data1(data_reads1, data_writes1);
10465 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710466 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10467 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210468
[email protected]49639fa2011-12-20 23:22:4110469 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210470
tfarina42834112016-09-22 13:38:2010471 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110472 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210473
10474 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110475 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210476
bnc691fda62016-08-12 00:43:1610477 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210478 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810479 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210480
[email protected]49639fa2011-12-20 23:22:4110481 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210482
bnc691fda62016-08-12 00:43:1610483 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10484 callback2.callback());
robpercival214763f2016-07-01 23:27:0110485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210486
10487 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110488 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210489
bnc691fda62016-08-12 00:43:1610490 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210491 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810492 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210493 }
10494
10495 // ------------------------------------------------------------------------
10496
10497 // Transaction 2: Request another resource in digestive's protection space.
10498 // This will preemptively add an Authorization header which should have an
10499 // "nc" value of 2 (as compared to 1 in the first use.
10500 {
[email protected]3c32c5f2010-05-18 15:18:1210501 HttpRequestInfo request;
10502 request.method = "GET";
10503 // Note that Transaction 1 was at /x/y/z, so this is in the same
10504 // protection space as digest.
bncce36dca22015-04-21 22:11:2310505 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010506 request.traffic_annotation =
10507 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210508
bnc691fda62016-08-12 00:43:1610509 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710510
[email protected]3c32c5f2010-05-18 15:18:1210511 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310512 MockWrite(
10513 "GET /x/y/a/b HTTP/1.1\r\n"
10514 "Host: www.example.org\r\n"
10515 "Connection: keep-alive\r\n"
10516 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10517 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10518 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10519 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210520 };
10521
10522 // Sever accepts the authorization.
10523 MockRead data_reads1[] = {
10524 MockRead("HTTP/1.0 200 OK\r\n"),
10525 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610526 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210527 };
10528
Ryan Sleevib8d7ea02018-05-07 20:01:0110529 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710530 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210531
[email protected]49639fa2011-12-20 23:22:4110532 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210533
tfarina42834112016-09-22 13:38:2010534 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110535 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210536
10537 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110538 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210539
bnc691fda62016-08-12 00:43:1610540 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210541 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810542 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210543 }
10544}
10545
[email protected]89ceba9a2009-03-21 03:46:0610546// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110547TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610548 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910549 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610550 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610551
10552 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410553 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610554 trans.read_buf_len_ = 15;
10555 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610556
10557 // Setup state in response_
bnc691fda62016-08-12 00:43:1610558 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810559 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810560 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710561 response->response_time = base::Time::Now();
10562 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610563
10564 { // Setup state for response_.vary_data
10565 HttpRequestInfo request;
10566 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10567 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710568 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310569 request.extra_headers.SetHeader("Foo", "1");
10570 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010571 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610572 }
10573
10574 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610575 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610576
10577 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610578 EXPECT_FALSE(trans.read_buf_);
10579 EXPECT_EQ(0, trans.read_buf_len_);
10580 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810581 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210582 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410583 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810584 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710585 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610586}
10587
[email protected]bacff652009-03-31 17:50:3310588// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110589TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310590 HttpRequestInfo request;
10591 request.method = "GET";
bncce36dca22015-04-21 22:11:2310592 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010593 request.traffic_annotation =
10594 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310595
danakj1fd259a02016-04-16 03:17:0910596 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610597 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710598
[email protected]bacff652009-03-31 17:50:3310599 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310600 MockWrite(
10601 "GET / HTTP/1.1\r\n"
10602 "Host: www.example.org\r\n"
10603 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310604 };
10605
10606 MockRead data_reads[] = {
10607 MockRead("HTTP/1.0 200 OK\r\n"),
10608 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10609 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610610 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310611 };
10612
[email protected]5ecc992a42009-11-11 01:41:5910613 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110614 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610615 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10616 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310617
[email protected]bb88e1d32013-05-03 23:11:0710618 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10619 session_deps_.socket_factory->AddSocketDataProvider(&data);
10620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10621 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310622
[email protected]49639fa2011-12-20 23:22:4110623 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310624
tfarina42834112016-09-22 13:38:2010625 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110626 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310627
10628 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110629 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310630
bnc691fda62016-08-12 00:43:1610631 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310633
10634 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110635 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310636
bnc691fda62016-08-12 00:43:1610637 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310638
wezca1070932016-05-26 20:30:5210639 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310640 EXPECT_EQ(100, response->headers->GetContentLength());
10641}
10642
10643// Test HTTPS connections to a site with a bad certificate, going through a
10644// proxy
bncd16676a2016-07-20 16:23:0110645TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610646 session_deps_.proxy_resolution_service =
10647 ConfiguredProxyResolutionService::CreateFixed(
10648 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310649
10650 HttpRequestInfo request;
10651 request.method = "GET";
bncce36dca22015-04-21 22:11:2310652 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010653 request.traffic_annotation =
10654 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310655
10656 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710657 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10658 "Host: www.example.org:443\r\n"
10659 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310660 };
10661
10662 MockRead proxy_reads[] = {
10663 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610664 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310665 };
10666
10667 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710668 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10669 "Host: www.example.org:443\r\n"
10670 "Proxy-Connection: keep-alive\r\n\r\n"),
10671 MockWrite("GET / HTTP/1.1\r\n"
10672 "Host: www.example.org\r\n"
10673 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310674 };
10675
10676 MockRead data_reads[] = {
10677 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10678 MockRead("HTTP/1.0 200 OK\r\n"),
10679 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10680 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610681 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310682 };
10683
Ryan Sleevib8d7ea02018-05-07 20:01:0110684 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10685 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610686 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10687 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310688
[email protected]bb88e1d32013-05-03 23:11:0710689 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10690 session_deps_.socket_factory->AddSocketDataProvider(&data);
10691 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10692 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310693
[email protected]49639fa2011-12-20 23:22:4110694 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310695
10696 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710697 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310698
danakj1fd259a02016-04-16 03:17:0910699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310701
tfarina42834112016-09-22 13:38:2010702 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110703 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310704
10705 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110706 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310707
bnc691fda62016-08-12 00:43:1610708 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110709 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310710
10711 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110712 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310713
bnc691fda62016-08-12 00:43:1610714 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310715
wezca1070932016-05-26 20:30:5210716 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310717 EXPECT_EQ(100, response->headers->GetContentLength());
10718 }
10719}
10720
[email protected]2df19bb2010-08-25 20:13:4610721
10722// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110723TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910724 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610725 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910726 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410727 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710728 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610729
10730 HttpRequestInfo request;
10731 request.method = "GET";
bncce36dca22015-04-21 22:11:2310732 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010733 request.traffic_annotation =
10734 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610735
10736 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710737 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10738 "Host: www.example.org:443\r\n"
10739 "Proxy-Connection: keep-alive\r\n\r\n"),
10740 MockWrite("GET / HTTP/1.1\r\n"
10741 "Host: www.example.org\r\n"
10742 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610743 };
10744
10745 MockRead data_reads[] = {
10746 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10747 MockRead("HTTP/1.1 200 OK\r\n"),
10748 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10749 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610750 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610751 };
10752
Ryan Sleevib8d7ea02018-05-07 20:01:0110753 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610754 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10755 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610756
[email protected]bb88e1d32013-05-03 23:11:0710757 session_deps_.socket_factory->AddSocketDataProvider(&data);
10758 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10759 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610760
[email protected]49639fa2011-12-20 23:22:4110761 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610762
danakj1fd259a02016-04-16 03:17:0910763 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610764 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610765
tfarina42834112016-09-22 13:38:2010766 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110767 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610768
10769 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110770 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610771 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610772
wezca1070932016-05-26 20:30:5210773 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610774
tbansal2ecbbc72016-10-06 17:15:4710775 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610776 EXPECT_TRUE(response->headers->IsKeepAlive());
10777 EXPECT_EQ(200, response->headers->response_code());
10778 EXPECT_EQ(100, response->headers->GetContentLength());
10779 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010780
10781 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610782 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010783 TestLoadTimingNotReusedWithPac(load_timing_info,
10784 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610785}
10786
Eric Roman695a7872019-04-16 21:53:2910787// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110788TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910789 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610790 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910791 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410792 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710793 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910794
Matt Menkeecfecfc72019-02-05 19:15:2810795 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10796 session_deps_.host_resolver->set_ondemand_mode(true);
10797
[email protected]511f6f52010-12-17 03:58:2910798 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210799 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910800 request.method = "GET";
bncce36dca22015-04-21 22:11:2310801 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010802 request.traffic_annotation =
10803 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910804
10805 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810806 MockWrite(ASYNC, 0,
10807 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710808 "Host: www.example.org:443\r\n"
10809 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910810 };
10811
10812 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810813 // Pause on first read.
10814 MockRead(ASYNC, ERR_IO_PENDING, 1),
10815 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10816 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10817 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910818 };
10819
Matt Menkeecfecfc72019-02-05 19:15:2810820 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610821 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910822
[email protected]bb88e1d32013-05-03 23:11:0710823 session_deps_.socket_factory->AddSocketDataProvider(&data);
10824 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910825
[email protected]49639fa2011-12-20 23:22:4110826 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910827
danakj1fd259a02016-04-16 03:17:0910828 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610829 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910830
tfarina42834112016-09-22 13:38:2010831 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810833 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10834
10835 // Host resolution takes |kTimeIncrement|.
10836 FastForwardBy(kTimeIncrement);
10837 // Resolving the current request with |ResolveNow| will cause the pending
10838 // request to instantly complete, and the async connect will start as well.
10839 session_deps_.host_resolver->ResolveOnlyRequestNow();
10840
10841 // Connecting takes |kTimeIncrement|.
10842 FastForwardBy(kTimeIncrement);
10843 data.RunUntilPaused();
10844
10845 // The server takes |kTimeIncrement| to respond.
10846 FastForwardBy(kTimeIncrement);
10847 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910848
10849 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910850 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910851}
10852
Eric Roman74103c72019-02-21 00:23:1210853// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10854TEST_F(HttpNetworkTransactionTest,
10855 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10856 base::HistogramTester histograms;
10857 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610858 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Eric Roman74103c72019-02-21 00:23:1210859 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410860 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210861 session_deps_.net_log = &net_log;
10862
10863 HttpRequestInfo request;
10864 request.method = "GET";
10865 request.url = GURL("https://www.example.org/");
10866 request.traffic_annotation =
10867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10868
10869 MockWrite data_writes[] = {
10870 MockWrite(ASYNC, 0,
10871 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10872 "Host: www.example.org:443\r\n"
10873 "Proxy-Connection: keep-alive\r\n\r\n"),
10874 };
10875
10876 MockRead data_reads[] = {
10877 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10878 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10879 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10880 };
10881
10882 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10883 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10884
10885 session_deps_.socket_factory->AddSocketDataProvider(&data);
10886 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10887
10888 TestCompletionCallback callback;
10889
10890 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10891 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10892
10893 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10894 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10895
10896 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910897 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210898}
10899
10900// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10901// request for main frames.
10902TEST_F(HttpNetworkTransactionTest,
10903 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10904 base::HistogramTester histograms;
10905 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610906 ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
Eric Roman74103c72019-02-21 00:23:1210907 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410908 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210909 session_deps_.net_log = &net_log;
10910
10911 HttpRequestInfo request;
10912 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10913 request.method = "GET";
10914 request.url = GURL("https://www.example.org/");
10915 request.traffic_annotation =
10916 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10917
10918 MockWrite data_writes[] = {
10919 MockWrite(ASYNC, 0,
10920 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10921 "Host: www.example.org:443\r\n"
10922 "Proxy-Connection: keep-alive\r\n\r\n"),
10923 };
10924
10925 MockRead data_reads[] = {
10926 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10927 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10928 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10929 };
10930
10931 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10932 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10933
10934 session_deps_.socket_factory->AddSocketDataProvider(&data);
10935 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10936
10937 TestCompletionCallback callback;
10938
10939 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10940 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10941
10942 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10944
10945 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910946 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210947}
10948
Eric Roman695a7872019-04-16 21:53:2910949// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210950// frames.
bncd16676a2016-07-20 16:23:0110951TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210952 base::HistogramTester histograms;
Nicolas Arciniegad2013f92020-02-07 23:00:5610953 session_deps_.proxy_resolution_service =
10954 ConfiguredProxyResolutionService::CreateFixed(
10955 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410956 RecordingTestNetLog net_log;
Matt Menkeecfecfc72019-02-05 19:15:2810957 session_deps_.net_log = &net_log;
10958
Matt Menkeecfecfc72019-02-05 19:15:2810959 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10960 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910961
10962 HttpRequestInfo request;
10963 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210964 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310965 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010966 request.traffic_annotation =
10967 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910968
Ryan Hamilton0239aac2018-05-19 00:03:1310969 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410970 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10971 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310972 spdy::SpdySerializedFrame goaway(
10973 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910974 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110975 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810976 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910977 };
10978
10979 static const char* const kExtraHeaders[] = {
10980 "location",
10981 "http://login.example.com/",
10982 };
Ryan Hamilton0239aac2018-05-19 00:03:1310983 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410984 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910985 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810986 // Pause on first read.
10987 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10988 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910989 };
10990
Matt Menkeecfecfc72019-02-05 19:15:2810991 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610992 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610993 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910994
[email protected]bb88e1d32013-05-03 23:11:0710995 session_deps_.socket_factory->AddSocketDataProvider(&data);
10996 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910997
[email protected]49639fa2011-12-20 23:22:4110998 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910999
danakj1fd259a02016-04-16 03:17:0911000 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611001 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911002
tfarina42834112016-09-22 13:38:2011003 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111004 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2811005 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2911006
Matt Menkeecfecfc72019-02-05 19:15:2811007 // Host resolution takes |kTimeIncrement|.
11008 FastForwardBy(kTimeIncrement);
11009 // Resolving the current request with |ResolveNow| will cause the pending
11010 // request to instantly complete, and the async connect will start as well.
11011 session_deps_.host_resolver->ResolveOnlyRequestNow();
11012
11013 // Connecting takes |kTimeIncrement|.
11014 FastForwardBy(kTimeIncrement);
11015 data.RunUntilPaused();
11016
11017 FastForwardBy(kTimeIncrement);
11018 data.Resume();
[email protected]511f6f52010-12-17 03:58:2911019 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5911020 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911021}
11022
[email protected]4eddbc732012-08-09 05:40:1711023// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111024TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611025 session_deps_.proxy_resolution_service =
11026 ConfiguredProxyResolutionService::CreateFixed(
11027 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911028
11029 HttpRequestInfo request;
11030 request.method = "GET";
bncce36dca22015-04-21 22:11:2311031 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011032 request.traffic_annotation =
11033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911034
11035 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711036 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11037 "Host: www.example.org:443\r\n"
11038 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2911039 };
11040
11041 MockRead data_reads[] = {
11042 MockRead("HTTP/1.1 404 Not Found\r\n"),
11043 MockRead("Content-Length: 23\r\n\r\n"),
11044 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0611045 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2911046 };
11047
Ryan Sleevib8d7ea02018-05-07 20:01:0111048 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611049 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2911050
[email protected]bb88e1d32013-05-03 23:11:0711051 session_deps_.socket_factory->AddSocketDataProvider(&data);
11052 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911053
[email protected]49639fa2011-12-20 23:22:4111054 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911055
danakj1fd259a02016-04-16 03:17:0911056 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611057 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911058
tfarina42834112016-09-22 13:38:2011059 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911061
11062 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111063 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911064
ttuttle960fcbf2016-04-19 13:26:3211065 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911066}
11067
[email protected]4eddbc732012-08-09 05:40:1711068// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111069TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611070 session_deps_.proxy_resolution_service =
11071 ConfiguredProxyResolutionService::CreateFixed(
11072 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911073
11074 HttpRequestInfo request;
11075 request.method = "GET";
bncce36dca22015-04-21 22:11:2311076 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011077 request.traffic_annotation =
11078 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911079
Ryan Hamilton0239aac2018-05-19 00:03:1311080 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411081 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11082 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311083 spdy::SpdySerializedFrame rst(
11084 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2911085 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111086 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2911087 };
11088
11089 static const char* const kExtraHeaders[] = {
11090 "location",
11091 "http://login.example.com/",
11092 };
Ryan Hamilton0239aac2018-05-19 00:03:1311093 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411094 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1311095 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1911096 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2911097 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111098 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1311099 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2911100 };
11101
Ryan Sleevib8d7ea02018-05-07 20:01:0111102 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611103 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3611104 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2911105
[email protected]bb88e1d32013-05-03 23:11:0711106 session_deps_.socket_factory->AddSocketDataProvider(&data);
11107 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911108
[email protected]49639fa2011-12-20 23:22:4111109 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911110
danakj1fd259a02016-04-16 03:17:0911111 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611112 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911113
tfarina42834112016-09-22 13:38:2011114 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111115 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911116
11117 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111118 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911119
ttuttle960fcbf2016-04-19 13:26:3211120 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911121}
11122
[email protected]0c5fb722012-02-28 11:50:3511123// Test the request-challenge-retry sequence for basic auth, through
11124// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0111125TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3511126 HttpRequestInfo request;
11127 request.method = "GET";
bncce36dca22015-04-21 22:11:2311128 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3511129 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:0011130 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e2018-02-07 07:41:1011131 request.traffic_annotation =
11132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3511133
11134 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5911135 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611136 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911137 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411138 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711139 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0911140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3511141
11142 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1311143 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411144 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11145 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311146 spdy::SpdySerializedFrame rst(
11147 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3811148 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3511149
bnc691fda62016-08-12 00:43:1611150 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3511151 // be issuing -- the final header line contains the credentials.
11152 const char* const kAuthCredentials[] = {
11153 "proxy-authorization", "Basic Zm9vOmJhcg==",
11154 };
Ryan Hamilton0239aac2018-05-19 00:03:1311155 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411156 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
11157 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2311158 HostPortPair("www.example.org", 443)));
11159 // fetch https://www.example.org/ via HTTP
11160 const char get[] =
11161 "GET / HTTP/1.1\r\n"
11162 "Host: www.example.org\r\n"
11163 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1311164 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1911165 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3511166
11167 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111168 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
11169 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3511170 };
11171
11172 // The proxy responds to the connect with a 407, using a persistent
11173 // connection.
thestig9d3bb0c2015-01-24 00:49:5111174 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3511175 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3511176 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
11177 };
Ryan Hamilton0239aac2018-05-19 00:03:1311178 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411179 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3511180
Ryan Hamilton0239aac2018-05-19 00:03:1311181 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3511182 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3511183 const char resp[] = "HTTP/1.1 200 OK\r\n"
11184 "Content-Length: 5\r\n\r\n";
11185
Ryan Hamilton0239aac2018-05-19 00:03:1311186 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1911187 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1311188 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1911189 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3511190 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111191 CreateMockRead(conn_auth_resp, 1, ASYNC),
11192 CreateMockRead(conn_resp, 4, ASYNC),
11193 CreateMockRead(wrapped_get_resp, 6, ASYNC),
11194 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1311195 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3511196 };
11197
Ryan Sleevib8d7ea02018-05-07 20:01:0111198 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711199 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3511200 // Negotiate SPDY to the proxy
11201 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611202 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711203 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3511204 // Vanilla SSL to the server
11205 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711206 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3511207
11208 TestCompletionCallback callback1;
11209
bnc87dcefc2017-05-25 12:47:5811210 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911211 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3511212
11213 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111214 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511215
11216 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111217 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5411218 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3511219 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0011220 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11221 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511222 ExpectLogContainsSomewhere(
11223 entries, pos,
mikecirone8b85c432016-09-08 19:11:0011224 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11225 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511226
11227 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211228 ASSERT_TRUE(response);
11229 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3511230 EXPECT_EQ(407, response->headers->response_code());
11231 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5811232 EXPECT_TRUE(response->auth_challenge.has_value());
11233 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3511234
11235 TestCompletionCallback callback2;
11236
11237 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
11238 callback2.callback());
robpercival214763f2016-07-01 23:27:0111239 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511240
11241 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111242 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3511243
11244 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211245 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3511246
11247 EXPECT_TRUE(response->headers->IsKeepAlive());
11248 EXPECT_EQ(200, response->headers->response_code());
11249 EXPECT_EQ(5, response->headers->GetContentLength());
11250 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11251
11252 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5811253 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3511254
[email protected]029c83b62013-01-24 05:28:2011255 LoadTimingInfo load_timing_info;
11256 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11257 TestLoadTimingNotReusedWithPac(load_timing_info,
11258 CONNECT_TIMING_HAS_SSL_TIMES);
11259
[email protected]0c5fb722012-02-28 11:50:3511260 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111261 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]0c5fb722012-02-28 11:50:3511262}
11263
[email protected]7c6f7ba2012-04-03 04:09:2911264// Test that an explicitly trusted SPDY proxy can push a resource from an
11265// origin that is different from that of its associated resource.
Matt Menkedf93ff72020-07-16 02:23:0311266TEST_F(HttpNetworkTransactionTest, CrossOriginSpdyProxyPush) {
tbansal28e68f82016-02-04 02:56:1511267 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911268 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511269 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11270 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2911271 HttpRequestInfo request;
11272 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1011273 request.traffic_annotation =
11274 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911275
[email protected]7c6f7ba2012-04-03 04:09:2911276 request.method = "GET";
bncce36dca22015-04-21 22:11:2311277 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2911278 push_request.method = "GET";
11279 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1011280 push_request.traffic_annotation =
11281 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911282
tbansal28e68f82016-02-04 02:56:1511283 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5911284 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611285 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911286 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411287 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711288 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011289
Eric Roman3d8546a2018-09-10 17:00:5211290 session_deps_.proxy_resolution_service->SetProxyDelegate(
11291 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011292
danakj1fd259a02016-04-16 03:17:0911293 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2911294
Ryan Hamilton0239aac2018-05-19 00:03:1311295 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511296 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311297 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511298 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2911299
11300 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111301 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511302 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2911303 };
11304
Ryan Hamilton0239aac2018-05-19 00:03:1311305 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511306 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3611307
Ryan Hamilton0239aac2018-05-19 00:03:1311308 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511309 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2911310
Ryan Hamilton0239aac2018-05-19 00:03:1311311 spdy::SpdySerializedFrame stream1_body(
11312 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2911313
Ryan Hamilton0239aac2018-05-19 00:03:1311314 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1911315 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2911316
11317 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3611318 CreateMockRead(stream2_syn, 1, ASYNC),
11319 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511320 CreateMockRead(stream1_body, 4, ASYNC),
11321 CreateMockRead(stream2_body, 5, ASYNC),
11322 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2911323 };
11324
Ryan Sleevib8d7ea02018-05-07 20:01:0111325 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711326 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2911327 // Negotiate SPDY to the proxy
11328 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611329 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711330 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2911331
bnc87dcefc2017-05-25 12:47:5811332 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911333 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2911334 TestCompletionCallback callback;
11335 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111336 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911337
11338 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111339 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911340 const HttpResponseInfo* response = trans->GetResponseInfo();
11341
bnc87dcefc2017-05-25 12:47:5811342 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1911343 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5011344 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111345 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911346
11347 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111348 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911349 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
11350
wezca1070932016-05-26 20:30:5211351 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2911352 EXPECT_TRUE(response->headers->IsKeepAlive());
11353
11354 EXPECT_EQ(200, response->headers->response_code());
11355 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11356
11357 std::string response_data;
11358 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111359 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911360 EXPECT_EQ("hello!", response_data);
11361
[email protected]029c83b62013-01-24 05:28:2011362 LoadTimingInfo load_timing_info;
11363 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11364 TestLoadTimingNotReusedWithPac(load_timing_info,
11365 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11366
[email protected]7c6f7ba2012-04-03 04:09:2911367 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5211368 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2911369 EXPECT_EQ(200, push_response->headers->response_code());
11370
11371 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111372 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911373 EXPECT_EQ("pushed", response_data);
11374
[email protected]029c83b62013-01-24 05:28:2011375 LoadTimingInfo push_load_timing_info;
11376 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
11377 TestLoadTimingReusedWithPac(push_load_timing_info);
11378 // The transactions should share a socket ID, despite being for different
11379 // origins.
11380 EXPECT_EQ(load_timing_info.socket_log_id,
11381 push_load_timing_info.socket_log_id);
11382
[email protected]7c6f7ba2012-04-03 04:09:2911383 trans.reset();
11384 push_trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111385 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]7c6f7ba2012-04-03 04:09:2911386}
11387
[email protected]8c843192012-04-05 07:15:0011388// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0111389TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511390 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911391 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511392 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11393 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0011394 HttpRequestInfo request;
11395
11396 request.method = "GET";
bncce36dca22015-04-21 22:11:2311397 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011398 request.traffic_annotation =
11399 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0011400
Nicolas Arciniegad2013f92020-02-07 23:00:5611401 session_deps_.proxy_resolution_service =
11402 ConfiguredProxyResolutionService::CreateFixed(
11403 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411404 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711405 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011406
11407 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211408 session_deps_.proxy_resolution_service->SetProxyDelegate(
11409 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011410
danakj1fd259a02016-04-16 03:17:0911411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0011412
Ryan Hamilton0239aac2018-05-19 00:03:1311413 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511414 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0011415
Ryan Hamilton0239aac2018-05-19 00:03:1311416 spdy::SpdySerializedFrame push_rst(
11417 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011418
11419 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111420 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011421 };
11422
Ryan Hamilton0239aac2018-05-19 00:03:1311423 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511424 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011425
Ryan Hamilton0239aac2018-05-19 00:03:1311426 spdy::SpdySerializedFrame stream1_body(
11427 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011428
Ryan Hamilton0239aac2018-05-19 00:03:1311429 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511430 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011431
11432 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111433 CreateMockRead(stream1_reply, 1, ASYNC),
11434 CreateMockRead(stream2_syn, 2, ASYNC),
11435 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911436 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011437 };
11438
Ryan Sleevib8d7ea02018-05-07 20:01:0111439 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711440 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011441 // Negotiate SPDY to the proxy
11442 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611443 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711444 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011445
bnc87dcefc2017-05-25 12:47:5811446 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911447 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011448 TestCompletionCallback callback;
11449 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111450 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011451
11452 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111453 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011454 const HttpResponseInfo* response = trans->GetResponseInfo();
11455
wezca1070932016-05-26 20:30:5211456 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011457 EXPECT_TRUE(response->headers->IsKeepAlive());
11458
11459 EXPECT_EQ(200, response->headers->response_code());
11460 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11461
11462 std::string response_data;
11463 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111464 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011465 EXPECT_EQ("hello!", response_data);
11466
11467 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111468 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]8c843192012-04-05 07:15:0011469}
11470
tbansal8ef1d3e2016-02-03 04:05:4211471// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11472// resources.
bncd16676a2016-07-20 16:23:0111473TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511474 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911475 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511476 proxy_delegate->set_trusted_spdy_proxy(
11477 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11478
tbansal8ef1d3e2016-02-03 04:05:4211479 HttpRequestInfo request;
11480
11481 request.method = "GET";
11482 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011483 request.traffic_annotation =
11484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211485
11486 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:5611487 session_deps_.proxy_resolution_service =
11488 ConfiguredProxyResolutionService::CreateFixed(
11489 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411490 RecordingBoundTestNetLog log;
tbansal8ef1d3e2016-02-03 04:05:4211491 session_deps_.net_log = log.bound().net_log();
11492
11493 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211494 session_deps_.proxy_resolution_service->SetProxyDelegate(
11495 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211496
danakj1fd259a02016-04-16 03:17:0911497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211498
Ryan Hamilton0239aac2018-05-19 00:03:1311499 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511500 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311501 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511502 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211503
11504 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111505 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511506 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211507 };
11508
Ryan Hamilton0239aac2018-05-19 00:03:1311509 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511510 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211511
Ryan Hamilton0239aac2018-05-19 00:03:1311512 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311513 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911514
Ryan Hamilton0239aac2018-05-19 00:03:1311515 spdy::SpdySerializedFrame stream1_body(
11516 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211517
Ryan Hamilton0239aac2018-05-19 00:03:1311518 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511519 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211520
Ryan Hamilton0239aac2018-05-19 00:03:1311521 spdy::SpdySerializedFrame stream2_body(
11522 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211523
11524 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111525 CreateMockRead(stream1_reply, 1, ASYNC),
11526 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511527 CreateMockRead(stream1_body, 4, ASYNC),
11528 CreateMockRead(stream2_body, 5, ASYNC),
11529 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211530 };
11531
Ryan Sleevib8d7ea02018-05-07 20:01:0111532 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211533 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11534 // Negotiate SPDY to the proxy
11535 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611536 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211537 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11538
bnc87dcefc2017-05-25 12:47:5811539 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911540 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211541 TestCompletionCallback callback;
11542 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211544
11545 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111546 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211547 const HttpResponseInfo* response = trans->GetResponseInfo();
11548
wezca1070932016-05-26 20:30:5211549 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211550 EXPECT_TRUE(response->headers->IsKeepAlive());
11551
11552 EXPECT_EQ(200, response->headers->response_code());
11553 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11554
11555 std::string response_data;
11556 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111557 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211558 EXPECT_EQ("hello!", response_data);
11559
11560 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111561 session->CloseAllConnections(ERR_FAILED, "Very good reason");
tbansal8ef1d3e2016-02-03 04:05:4211562}
11563
[email protected]2df19bb2010-08-25 20:13:4611564// Test HTTPS connections to a site with a bad certificate, going through an
11565// HTTPS proxy
bncd16676a2016-07-20 16:23:0111566TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611567 session_deps_.proxy_resolution_service =
11568 ConfiguredProxyResolutionService::CreateFixed(
11569 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611570
11571 HttpRequestInfo request;
11572 request.method = "GET";
bncce36dca22015-04-21 22:11:2311573 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011574 request.traffic_annotation =
11575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611576
11577 // Attempt to fetch the URL from a server with a bad cert
11578 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711579 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11580 "Host: www.example.org:443\r\n"
11581 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611582 };
11583
11584 MockRead bad_cert_reads[] = {
11585 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611586 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611587 };
11588
11589 // Attempt to fetch the URL with a good cert
11590 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711591 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11592 "Host: www.example.org:443\r\n"
11593 "Proxy-Connection: keep-alive\r\n\r\n"),
11594 MockWrite("GET / HTTP/1.1\r\n"
11595 "Host: www.example.org\r\n"
11596 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611597 };
11598
11599 MockRead good_cert_reads[] = {
11600 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11601 MockRead("HTTP/1.0 200 OK\r\n"),
11602 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11603 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611604 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611605 };
11606
Ryan Sleevib8d7ea02018-05-07 20:01:0111607 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11608 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611609 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11610 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611611
11612 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711613 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11614 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11615 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611616
11617 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711618 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11619 session_deps_.socket_factory->AddSocketDataProvider(&data);
11620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611621
[email protected]49639fa2011-12-20 23:22:4111622 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611623
danakj1fd259a02016-04-16 03:17:0911624 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611625 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611626
tfarina42834112016-09-22 13:38:2011627 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111628 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611629
11630 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111631 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611632
bnc691fda62016-08-12 00:43:1611633 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111634 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611635
11636 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111637 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611638
bnc691fda62016-08-12 00:43:1611639 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611640
wezca1070932016-05-26 20:30:5211641 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611642 EXPECT_EQ(100, response->headers->GetContentLength());
11643}
11644
bncd16676a2016-07-20 16:23:0111645TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211646 HttpRequestInfo request;
11647 request.method = "GET";
bncce36dca22015-04-21 22:11:2311648 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311649 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11650 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1011651 request.traffic_annotation =
11652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211653
danakj1fd259a02016-04-16 03:17:0911654 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611655 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711656
[email protected]1c773ea12009-04-28 19:58:4211657 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311658 MockWrite(
11659 "GET / HTTP/1.1\r\n"
11660 "Host: www.example.org\r\n"
11661 "Connection: keep-alive\r\n"
11662 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211663 };
11664
11665 // Lastly, the server responds with the actual content.
11666 MockRead data_reads[] = {
11667 MockRead("HTTP/1.0 200 OK\r\n"),
11668 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11669 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611670 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211671 };
11672
Ryan Sleevib8d7ea02018-05-07 20:01:0111673 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711674 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211675
[email protected]49639fa2011-12-20 23:22:4111676 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211677
tfarina42834112016-09-22 13:38:2011678 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111679 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211680
11681 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111682 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211683}
11684
bncd16676a2016-07-20 16:23:0111685TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011686 // Test user agent values, used both for the request header of the original
11687 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11688 // no request header / no HttpUserAgentSettings object.
11689 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911690
Matt Menked732ea42019-03-08 12:05:0011691 for (const char* setting_user_agent : kTestUserAgents) {
11692 if (!setting_user_agent) {
11693 session_deps_.http_user_agent_settings.reset();
11694 } else {
11695 session_deps_.http_user_agent_settings =
11696 std::make_unique<StaticHttpUserAgentSettings>(
11697 std::string() /* accept-language */, setting_user_agent);
11698 }
11699 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611700 ConfiguredProxyResolutionService::CreateFixed(
11701 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked732ea42019-03-08 12:05:0011702 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11703 for (const char* request_user_agent : kTestUserAgents) {
11704 HttpRequestInfo request;
11705 request.method = "GET";
11706 request.url = GURL("https://www.example.org/");
11707 if (request_user_agent) {
11708 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11709 request_user_agent);
11710 }
11711 request.traffic_annotation =
11712 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711713
Matt Menked732ea42019-03-08 12:05:0011714 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911715
Matt Menked732ea42019-03-08 12:05:0011716 std::string expected_request;
11717 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11718 expected_request =
11719 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11720 "Host: www.example.org:443\r\n"
11721 "Proxy-Connection: keep-alive\r\n\r\n";
11722 } else {
11723 expected_request = base::StringPrintf(
11724 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11725 "Host: www.example.org:443\r\n"
11726 "Proxy-Connection: keep-alive\r\n"
11727 "User-Agent: %s\r\n\r\n",
11728 setting_user_agent);
11729 }
11730 MockWrite data_writes[] = {
11731 MockWrite(expected_request.c_str()),
11732 };
11733 MockRead data_reads[] = {
11734 // Return an error, so the transaction stops here (this test isn't
11735 // interested in the rest).
11736 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11737 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11738 MockRead("Proxy-Connection: close\r\n\r\n"),
11739 };
[email protected]da81f132010-08-18 23:39:2911740
Matt Menked732ea42019-03-08 12:05:0011741 StaticSocketDataProvider data(data_reads, data_writes);
11742 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911743
Matt Menked732ea42019-03-08 12:05:0011744 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911745
Matt Menked732ea42019-03-08 12:05:0011746 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11747 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11748
11749 rv = callback.WaitForResult();
11750 EXPECT_THAT(rv, IsOk());
11751 }
11752 }
[email protected]da81f132010-08-18 23:39:2911753}
11754
bncd16676a2016-07-20 16:23:0111755TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211756 HttpRequestInfo request;
11757 request.method = "GET";
bncce36dca22015-04-21 22:11:2311758 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611759 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11760 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011761 request.traffic_annotation =
11762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211763
danakj1fd259a02016-04-16 03:17:0911764 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611765 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711766
[email protected]1c773ea12009-04-28 19:58:4211767 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311768 MockWrite(
11769 "GET / HTTP/1.1\r\n"
11770 "Host: www.example.org\r\n"
11771 "Connection: keep-alive\r\n"
11772 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211773 };
11774
11775 // Lastly, the server responds with the actual content.
11776 MockRead data_reads[] = {
11777 MockRead("HTTP/1.0 200 OK\r\n"),
11778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11779 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611780 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211781 };
11782
Ryan Sleevib8d7ea02018-05-07 20:01:0111783 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711784 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211785
[email protected]49639fa2011-12-20 23:22:4111786 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211787
tfarina42834112016-09-22 13:38:2011788 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111789 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211790
11791 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111792 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211793}
11794
bncd16676a2016-07-20 16:23:0111795TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211796 HttpRequestInfo request;
11797 request.method = "POST";
bncce36dca22015-04-21 22:11:2311798 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011799 request.traffic_annotation =
11800 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211801
danakj1fd259a02016-04-16 03:17:0911802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611803 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711804
[email protected]1c773ea12009-04-28 19:58:4211805 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311806 MockWrite(
11807 "POST / HTTP/1.1\r\n"
11808 "Host: www.example.org\r\n"
11809 "Connection: keep-alive\r\n"
11810 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211811 };
11812
11813 // Lastly, the server responds with the actual content.
11814 MockRead data_reads[] = {
11815 MockRead("HTTP/1.0 200 OK\r\n"),
11816 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11817 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611818 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211819 };
11820
Ryan Sleevib8d7ea02018-05-07 20:01:0111821 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711822 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211823
[email protected]49639fa2011-12-20 23:22:4111824 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211825
tfarina42834112016-09-22 13:38:2011826 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111827 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211828
11829 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111830 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211831}
11832
bncd16676a2016-07-20 16:23:0111833TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211834 HttpRequestInfo request;
11835 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311836 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011837 request.traffic_annotation =
11838 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211839
danakj1fd259a02016-04-16 03:17:0911840 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611841 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711842
[email protected]1c773ea12009-04-28 19:58:4211843 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311844 MockWrite(
11845 "PUT / HTTP/1.1\r\n"
11846 "Host: www.example.org\r\n"
11847 "Connection: keep-alive\r\n"
11848 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211849 };
11850
11851 // Lastly, the server responds with the actual content.
11852 MockRead data_reads[] = {
11853 MockRead("HTTP/1.0 200 OK\r\n"),
11854 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11855 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611856 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211857 };
11858
Ryan Sleevib8d7ea02018-05-07 20:01:0111859 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711860 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211861
[email protected]49639fa2011-12-20 23:22:4111862 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211863
tfarina42834112016-09-22 13:38:2011864 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111865 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211866
11867 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111868 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211869}
11870
bncd16676a2016-07-20 16:23:0111871TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211872 HttpRequestInfo request;
11873 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311874 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011875 request.traffic_annotation =
11876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211877
danakj1fd259a02016-04-16 03:17:0911878 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611879 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711880
[email protected]1c773ea12009-04-28 19:58:4211881 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311882 MockWrite("HEAD / HTTP/1.1\r\n"
11883 "Host: www.example.org\r\n"
11884 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211885 };
11886
11887 // Lastly, the server responds with the actual content.
11888 MockRead data_reads[] = {
11889 MockRead("HTTP/1.0 200 OK\r\n"),
11890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611892 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211893 };
11894
Ryan Sleevib8d7ea02018-05-07 20:01:0111895 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711896 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211897
[email protected]49639fa2011-12-20 23:22:4111898 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211899
tfarina42834112016-09-22 13:38:2011900 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111901 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211902
11903 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111904 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211905}
11906
bncd16676a2016-07-20 16:23:0111907TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211908 HttpRequestInfo request;
11909 request.method = "GET";
bncce36dca22015-04-21 22:11:2311910 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211911 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011912 request.traffic_annotation =
11913 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211914
danakj1fd259a02016-04-16 03:17:0911915 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611916 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711917
[email protected]1c773ea12009-04-28 19:58:4211918 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311919 MockWrite(
11920 "GET / HTTP/1.1\r\n"
11921 "Host: www.example.org\r\n"
11922 "Connection: keep-alive\r\n"
11923 "Pragma: no-cache\r\n"
11924 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211925 };
11926
11927 // Lastly, the server responds with the actual content.
11928 MockRead data_reads[] = {
11929 MockRead("HTTP/1.0 200 OK\r\n"),
11930 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11931 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611932 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211933 };
11934
Ryan Sleevib8d7ea02018-05-07 20:01:0111935 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711936 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211937
[email protected]49639fa2011-12-20 23:22:4111938 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211939
tfarina42834112016-09-22 13:38:2011940 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111941 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211942
11943 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111944 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211945}
11946
bncd16676a2016-07-20 16:23:0111947TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211948 HttpRequestInfo request;
11949 request.method = "GET";
bncce36dca22015-04-21 22:11:2311950 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211951 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011952 request.traffic_annotation =
11953 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211954
danakj1fd259a02016-04-16 03:17:0911955 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611956 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711957
[email protected]1c773ea12009-04-28 19:58:4211958 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311959 MockWrite(
11960 "GET / HTTP/1.1\r\n"
11961 "Host: www.example.org\r\n"
11962 "Connection: keep-alive\r\n"
11963 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211964 };
11965
11966 // Lastly, the server responds with the actual content.
11967 MockRead data_reads[] = {
11968 MockRead("HTTP/1.0 200 OK\r\n"),
11969 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11970 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611971 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211972 };
11973
Ryan Sleevib8d7ea02018-05-07 20:01:0111974 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711975 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211976
[email protected]49639fa2011-12-20 23:22:4111977 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211978
tfarina42834112016-09-22 13:38:2011979 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111980 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211981
11982 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111983 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211984}
11985
bncd16676a2016-07-20 16:23:0111986TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211987 HttpRequestInfo request;
11988 request.method = "GET";
bncce36dca22015-04-21 22:11:2311989 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311990 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1011991 request.traffic_annotation =
11992 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211993
danakj1fd259a02016-04-16 03:17:0911994 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611995 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711996
[email protected]1c773ea12009-04-28 19:58:4211997 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311998 MockWrite(
11999 "GET / HTTP/1.1\r\n"
12000 "Host: www.example.org\r\n"
12001 "Connection: keep-alive\r\n"
12002 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4212003 };
12004
12005 // Lastly, the server responds with the actual content.
12006 MockRead data_reads[] = {
12007 MockRead("HTTP/1.0 200 OK\r\n"),
12008 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12009 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612010 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4212011 };
12012
Ryan Sleevib8d7ea02018-05-07 20:01:0112013 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712014 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4212015
[email protected]49639fa2011-12-20 23:22:4112016 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4212017
tfarina42834112016-09-22 13:38:2012018 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112019 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212020
12021 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112022 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212023}
12024
bncd16676a2016-07-20 16:23:0112025TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4712026 HttpRequestInfo request;
12027 request.method = "GET";
bncce36dca22015-04-21 22:11:2312028 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4312029 request.extra_headers.SetHeader("referer", "www.foo.com");
12030 request.extra_headers.SetHeader("hEllo", "Kitty");
12031 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1012032 request.traffic_annotation =
12033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4712034
danakj1fd259a02016-04-16 03:17:0912035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712037
[email protected]270c6412010-03-29 22:02:4712038 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312039 MockWrite(
12040 "GET / HTTP/1.1\r\n"
12041 "Host: www.example.org\r\n"
12042 "Connection: keep-alive\r\n"
12043 "referer: www.foo.com\r\n"
12044 "hEllo: Kitty\r\n"
12045 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4712046 };
12047
12048 // Lastly, the server responds with the actual content.
12049 MockRead data_reads[] = {
12050 MockRead("HTTP/1.0 200 OK\r\n"),
12051 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12052 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612053 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4712054 };
12055
Ryan Sleevib8d7ea02018-05-07 20:01:0112056 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712057 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4712058
[email protected]49639fa2011-12-20 23:22:4112059 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4712060
tfarina42834112016-09-22 13:38:2012061 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4712063
12064 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112065 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4712066}
12067
bncd16676a2016-07-20 16:23:0112068TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712069 HttpRequestInfo request;
12070 request.method = "GET";
bncce36dca22015-04-21 22:11:2312071 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012072 request.traffic_annotation =
12073 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712074
Lily Houghton8c2f97d2018-01-22 05:06:5912075 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612076 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912077 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412078 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712079 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212080
danakj1fd259a02016-04-16 03:17:0912081 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612082 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212083
[email protected]3cd17242009-06-23 02:59:0212084 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12085 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12086
12087 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412088 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12089 MockWrite("GET / HTTP/1.1\r\n"
12090 "Host: www.example.org\r\n"
12091 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212092
12093 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412094 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12095 MockRead("HTTP/1.0 200 OK\r\n"),
12096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12097 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212098
Ryan Sleevib8d7ea02018-05-07 20:01:0112099 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712100 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212101
[email protected]49639fa2011-12-20 23:22:4112102 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212103
tfarina42834112016-09-22 13:38:2012104 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112105 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212106
12107 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112108 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212109
bnc691fda62016-08-12 00:43:1612110 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212111 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0212112
tbansal2ecbbc72016-10-06 17:15:4712113 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2012114 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612115 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012116 TestLoadTimingNotReusedWithPac(load_timing_info,
12117 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12118
[email protected]3cd17242009-06-23 02:59:0212119 std::string response_text;
bnc691fda62016-08-12 00:43:1612120 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112121 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212122 EXPECT_EQ("Payload", response_text);
12123}
12124
bncd16676a2016-07-20 16:23:0112125TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712126 HttpRequestInfo request;
12127 request.method = "GET";
bncce36dca22015-04-21 22:11:2312128 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012129 request.traffic_annotation =
12130 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712131
Lily Houghton8c2f97d2018-01-22 05:06:5912132 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612133 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912134 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412135 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712136 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212137
danakj1fd259a02016-04-16 03:17:0912138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212140
[email protected]3cd17242009-06-23 02:59:0212141 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
12142 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12143
12144 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312145 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2412146 base::size(write_buffer)),
12147 MockWrite("GET / HTTP/1.1\r\n"
12148 "Host: www.example.org\r\n"
12149 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212150
12151 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412152 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
12153 base::size(read_buffer)),
12154 MockRead("HTTP/1.0 200 OK\r\n"),
12155 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12156 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512157
Ryan Sleevib8d7ea02018-05-07 20:01:0112158 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712159 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512160
[email protected]8ddf8322012-02-23 18:08:0612161 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712162 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3512163
[email protected]49639fa2011-12-20 23:22:4112164 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512165
tfarina42834112016-09-22 13:38:2012166 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512168
12169 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112170 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512171
[email protected]029c83b62013-01-24 05:28:2012172 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612173 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012174 TestLoadTimingNotReusedWithPac(load_timing_info,
12175 CONNECT_TIMING_HAS_SSL_TIMES);
12176
bnc691fda62016-08-12 00:43:1612177 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212178 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712179 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512180
12181 std::string response_text;
bnc691fda62016-08-12 00:43:1612182 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112183 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512184 EXPECT_EQ("Payload", response_text);
12185}
12186
bncd16676a2016-07-20 16:23:0112187TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2012188 HttpRequestInfo request;
12189 request.method = "GET";
bncce36dca22015-04-21 22:11:2312190 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012191 request.traffic_annotation =
12192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2012193
Nicolas Arciniegad2013f92020-02-07 23:00:5612194 session_deps_.proxy_resolution_service =
12195 ConfiguredProxyResolutionService::CreateFixed(
12196 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412197 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712198 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2012199
danakj1fd259a02016-04-16 03:17:0912200 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612201 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2012202
12203 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12204 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12205
12206 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412207 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12208 MockWrite("GET / HTTP/1.1\r\n"
12209 "Host: www.example.org\r\n"
12210 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2012211
12212 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412213 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12214 MockRead("HTTP/1.0 200 OK\r\n"),
12215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12216 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2012217
Ryan Sleevib8d7ea02018-05-07 20:01:0112218 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712219 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2012220
12221 TestCompletionCallback callback;
12222
tfarina42834112016-09-22 13:38:2012223 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112224 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2012225
12226 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112227 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012228
bnc691fda62016-08-12 00:43:1612229 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212230 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2012231
12232 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612233 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012234 TestLoadTimingNotReused(load_timing_info,
12235 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12236
12237 std::string response_text;
bnc691fda62016-08-12 00:43:1612238 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112239 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012240 EXPECT_EQ("Payload", response_text);
12241}
12242
bncd16676a2016-07-20 16:23:0112243TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712244 HttpRequestInfo request;
12245 request.method = "GET";
bncce36dca22015-04-21 22:11:2312246 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012247 request.traffic_annotation =
12248 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712249
Lily Houghton8c2f97d2018-01-22 05:06:5912250 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612251 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912252 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412253 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712254 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512255
danakj1fd259a02016-04-16 03:17:0912256 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612257 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512258
[email protected]e0c27be2009-07-15 13:09:3512259 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12260 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712261 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312262 0x05, // Version
12263 0x01, // Command (CONNECT)
12264 0x00, // Reserved.
12265 0x03, // Address type (DOMAINNAME).
12266 0x0F, // Length of domain (15)
12267 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12268 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3712269 };
[email protected]e0c27be2009-07-15 13:09:3512270 const char kSOCKS5OkResponse[] =
12271 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
12272
12273 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412274 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
12275 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
12276 MockWrite("GET / HTTP/1.1\r\n"
12277 "Host: www.example.org\r\n"
12278 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512279
12280 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412281 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12282 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12283 MockRead("HTTP/1.0 200 OK\r\n"),
12284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12285 MockRead("Payload"),
12286 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512287
Ryan Sleevib8d7ea02018-05-07 20:01:0112288 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712289 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512290
[email protected]49639fa2011-12-20 23:22:4112291 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512292
tfarina42834112016-09-22 13:38:2012293 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112294 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512295
12296 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112297 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512298
bnc691fda62016-08-12 00:43:1612299 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212300 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712301 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512302
[email protected]029c83b62013-01-24 05:28:2012303 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612304 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012305 TestLoadTimingNotReusedWithPac(load_timing_info,
12306 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12307
[email protected]e0c27be2009-07-15 13:09:3512308 std::string response_text;
bnc691fda62016-08-12 00:43:1612309 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112310 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512311 EXPECT_EQ("Payload", response_text);
12312}
12313
bncd16676a2016-07-20 16:23:0112314TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712315 HttpRequestInfo request;
12316 request.method = "GET";
bncce36dca22015-04-21 22:11:2312317 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012318 request.traffic_annotation =
12319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712320
Lily Houghton8c2f97d2018-01-22 05:06:5912321 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612322 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912323 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412324 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712325 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512326
danakj1fd259a02016-04-16 03:17:0912327 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612328 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512329
[email protected]e0c27be2009-07-15 13:09:3512330 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12331 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712332 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312333 0x05, // Version
12334 0x01, // Command (CONNECT)
12335 0x00, // Reserved.
12336 0x03, // Address type (DOMAINNAME).
12337 0x0F, // Length of domain (15)
12338 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12339 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3712340 };
12341
[email protected]e0c27be2009-07-15 13:09:3512342 const char kSOCKS5OkResponse[] =
12343 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
12344
12345 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412346 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2312347 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2412348 base::size(kSOCKS5OkRequest)),
12349 MockWrite("GET / HTTP/1.1\r\n"
12350 "Host: www.example.org\r\n"
12351 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512352
12353 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412354 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12355 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12356 MockRead("HTTP/1.0 200 OK\r\n"),
12357 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12358 MockRead("Payload"),
12359 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212360
Ryan Sleevib8d7ea02018-05-07 20:01:0112361 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712362 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212363
[email protected]8ddf8322012-02-23 18:08:0612364 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712365 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0212366
[email protected]49639fa2011-12-20 23:22:4112367 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212368
tfarina42834112016-09-22 13:38:2012369 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212371
12372 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112373 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212374
bnc691fda62016-08-12 00:43:1612375 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212376 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712377 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0212378
[email protected]029c83b62013-01-24 05:28:2012379 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612380 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012381 TestLoadTimingNotReusedWithPac(load_timing_info,
12382 CONNECT_TIMING_HAS_SSL_TIMES);
12383
[email protected]3cd17242009-06-23 02:59:0212384 std::string response_text;
bnc691fda62016-08-12 00:43:1612385 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112386 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212387 EXPECT_EQ("Payload", response_text);
12388}
12389
[email protected]448d4ca52012-03-04 04:12:2312390namespace {
12391
Matt Menkef6edce752019-03-19 17:21:5612392// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0612393
Matt Menkef6edce752019-03-19 17:21:5612394struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0612395 std::string proxy_server;
12396 std::string url;
Matt Menkef6edce752019-03-19 17:21:5612397 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1812398 bool ssl;
[email protected]2d731a32010-04-29 01:04:0612399};
12400
Matt Menkef6edce752019-03-19 17:21:5612401std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0712402 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0912403 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0612404
bnc525e175a2016-06-20 12:36:4012405 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312406 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112407 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1212408 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112409 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4212410 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0712411 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0612412
12413 return session;
12414}
12415
Matt Menkef6edce752019-03-19 17:21:5612416int GroupIdTransactionHelper(const std::string& url,
12417 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0612418 HttpRequestInfo request;
12419 request.method = "GET";
12420 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1012421 request.traffic_annotation =
12422 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612423
bnc691fda62016-08-12 00:43:1612424 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712425
[email protected]49639fa2011-12-20 23:22:4112426 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612427
12428 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012429 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612430}
12431
[email protected]448d4ca52012-03-04 04:12:2312432} // namespace
12433
Matt Menkef6edce752019-03-19 17:21:5612434TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12435 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312436 {
Matt Menkef6edce752019-03-19 17:21:5612437 "", // unused
12438 "http://www.example.org/direct",
12439 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12440 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412441 PrivacyMode::PRIVACY_MODE_DISABLED,
12442 NetworkIsolationKey(),
12443 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612444 false,
bncce36dca22015-04-21 22:11:2312445 },
12446 {
Matt Menkef6edce752019-03-19 17:21:5612447 "", // unused
12448 "http://[2001:1418:13:1::25]/direct",
12449 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12450 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412451 PrivacyMode::PRIVACY_MODE_DISABLED,
12452 NetworkIsolationKey(),
12453 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612454 false,
bncce36dca22015-04-21 22:11:2312455 },
[email protected]04e5be32009-06-26 20:00:3112456
bncce36dca22015-04-21 22:11:2312457 // SSL Tests
12458 {
Matt Menkef6edce752019-03-19 17:21:5612459 "", // unused
12460 "https://www.example.org/direct_ssl",
12461 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12462 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412463 PrivacyMode::PRIVACY_MODE_DISABLED,
12464 NetworkIsolationKey(),
12465 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612466 true,
bncce36dca22015-04-21 22:11:2312467 },
12468 {
Matt Menkef6edce752019-03-19 17:21:5612469 "", // unused
12470 "https://[2001:1418:13:1::25]/direct",
12471 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12472 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412473 PrivacyMode::PRIVACY_MODE_DISABLED,
12474 NetworkIsolationKey(),
12475 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612476 true,
bncce36dca22015-04-21 22:11:2312477 },
12478 {
Matt Menkef6edce752019-03-19 17:21:5612479 "", // unused
12480 "https://host.with.alternate/direct",
12481 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12482 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412483 PrivacyMode::PRIVACY_MODE_DISABLED,
12484 NetworkIsolationKey(),
12485 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612486 true,
bncce36dca22015-04-21 22:11:2312487 },
[email protected]2d731a32010-04-29 01:04:0612488 };
[email protected]2ff8b312010-04-26 22:20:5412489
Avi Drissman4365a4782018-12-28 19:26:2412490 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912491 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612492 ConfiguredProxyResolutionService::CreateFixed(
12493 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912494 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612495 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612496
mmenkee65e7af2015-10-13 17:16:4212497 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612498 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612499 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912500 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012501 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12502 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812503 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612504
12505 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612506 GroupIdTransactionHelper(tests[i].url, session.get()));
12507 EXPECT_EQ(tests[i].expected_group_id,
12508 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312509 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612510 }
[email protected]2d731a32010-04-29 01:04:0612511}
12512
Matt Menkef6edce752019-03-19 17:21:5612513TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12514 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312515 {
Matt Menke4802de62019-03-08 22:47:5012516 "http_proxy",
12517 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612518 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12519 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412520 PrivacyMode::PRIVACY_MODE_DISABLED,
12521 NetworkIsolationKey(),
12522 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012523 false,
bncce36dca22015-04-21 22:11:2312524 },
[email protected]2d731a32010-04-29 01:04:0612525
bncce36dca22015-04-21 22:11:2312526 // SSL Tests
12527 {
Matt Menke4802de62019-03-08 22:47:5012528 "http_proxy",
12529 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612530 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12531 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412532 PrivacyMode::PRIVACY_MODE_DISABLED,
12533 NetworkIsolationKey(),
12534 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012535 true,
bncce36dca22015-04-21 22:11:2312536 },
[email protected]af3490e2010-10-16 21:02:2912537
bncce36dca22015-04-21 22:11:2312538 {
Matt Menke4802de62019-03-08 22:47:5012539 "http_proxy",
12540 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612541 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12542 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412543 PrivacyMode::PRIVACY_MODE_DISABLED,
12544 NetworkIsolationKey(),
12545 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012546 true,
bncce36dca22015-04-21 22:11:2312547 },
[email protected]2d731a32010-04-29 01:04:0612548 };
12549
Avi Drissman4365a4782018-12-28 19:26:2412550 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912551 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612552 ConfiguredProxyResolutionService::CreateFixed(
12553 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912554 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612555 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612556
mmenkee65e7af2015-10-13 17:16:4212557 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612558
Matt Menkee8648fa2019-01-17 16:47:0712559 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12560 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612561 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612562 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912563 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012564 mock_pool_manager->SetSocketPool(proxy_server,
12565 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812566 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612567
12568 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612569 GroupIdTransactionHelper(tests[i].url, session.get()));
12570 EXPECT_EQ(tests[i].expected_group_id,
12571 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612572 }
[email protected]2d731a32010-04-29 01:04:0612573}
12574
Matt Menkef6edce752019-03-19 17:21:5612575TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12576 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312577 {
Matt Menke4802de62019-03-08 22:47:5012578 "socks4://socks_proxy:1080",
12579 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612580 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12581 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412582 PrivacyMode::PRIVACY_MODE_DISABLED,
12583 NetworkIsolationKey(),
12584 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012585 false,
bncce36dca22015-04-21 22:11:2312586 },
12587 {
Matt Menke4802de62019-03-08 22:47:5012588 "socks5://socks_proxy:1080",
12589 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612590 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12591 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412592 PrivacyMode::PRIVACY_MODE_DISABLED,
12593 NetworkIsolationKey(),
12594 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012595 false,
bncce36dca22015-04-21 22:11:2312596 },
[email protected]2d731a32010-04-29 01:04:0612597
bncce36dca22015-04-21 22:11:2312598 // SSL Tests
12599 {
Matt Menke4802de62019-03-08 22:47:5012600 "socks4://socks_proxy:1080",
12601 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612602 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12603 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412604 PrivacyMode::PRIVACY_MODE_DISABLED,
12605 NetworkIsolationKey(),
12606 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012607 true,
bncce36dca22015-04-21 22:11:2312608 },
12609 {
Matt Menke4802de62019-03-08 22:47:5012610 "socks5://socks_proxy:1080",
12611 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612612 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12613 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412614 PrivacyMode::PRIVACY_MODE_DISABLED,
12615 NetworkIsolationKey(),
12616 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012617 true,
bncce36dca22015-04-21 22:11:2312618 },
[email protected]af3490e2010-10-16 21:02:2912619
bncce36dca22015-04-21 22:11:2312620 {
Matt Menke4802de62019-03-08 22:47:5012621 "socks4://socks_proxy:1080",
12622 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612623 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12624 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412625 PrivacyMode::PRIVACY_MODE_DISABLED,
12626 NetworkIsolationKey(),
12627 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012628 true,
bncce36dca22015-04-21 22:11:2312629 },
[email protected]04e5be32009-06-26 20:00:3112630 };
12631
Avi Drissman4365a4782018-12-28 19:26:2412632 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912633 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612634 ConfiguredProxyResolutionService::CreateFixed(
12635 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912636 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612637 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212638
mmenkee65e7af2015-10-13 17:16:4212639 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112640
Matt Menkee8648fa2019-01-17 16:47:0712641 ProxyServer proxy_server(
12642 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12643 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612644 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612645 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912646 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012647 mock_pool_manager->SetSocketPool(proxy_server,
12648 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812649 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112650
bnc691fda62016-08-12 00:43:1612651 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112652
[email protected]2d731a32010-04-29 01:04:0612653 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612654 GroupIdTransactionHelper(tests[i].url, session.get()));
12655 EXPECT_EQ(tests[i].expected_group_id,
12656 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112657 }
12658}
12659
bncd16676a2016-07-20 16:23:0112660TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712661 HttpRequestInfo request;
12662 request.method = "GET";
bncce36dca22015-04-21 22:11:2312663 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012664 request.traffic_annotation =
12665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712666
Nicolas Arciniegad2013f92020-02-07 23:00:5612667 session_deps_.proxy_resolution_service =
12668 ConfiguredProxyResolutionService::CreateFixed(
12669 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212670
[email protected]69719062010-01-05 20:09:2112671 // This simulates failure resolving all hostnames; that means we will fail
12672 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712673 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212674
danakj1fd259a02016-04-16 03:17:0912675 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612676 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512677
[email protected]49639fa2011-12-20 23:22:4112678 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512679
tfarina42834112016-09-22 13:38:2012680 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112681 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512682
[email protected]9172a982009-06-06 00:30:2512683 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112684 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512685}
12686
[email protected]0877e3d2009-10-17 22:29:5712687// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112688TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712689 HttpRequestInfo request;
12690 request.method = "GET";
12691 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012692 request.traffic_annotation =
12693 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712694
12695 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612696 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712697 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112698 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712699 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912700 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712701
[email protected]49639fa2011-12-20 23:22:4112702 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712703
bnc691fda62016-08-12 00:43:1612704 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712705
tfarina42834112016-09-22 13:38:2012706 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112707 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712708
12709 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112710 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912711
12712 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612713 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912714 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712715}
12716
zmo9528c9f42015-08-04 22:12:0812717// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112718TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712719 HttpRequestInfo request;
12720 request.method = "GET";
12721 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012722 request.traffic_annotation =
12723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712724
12725 MockRead data_reads[] = {
12726 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612727 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712728 };
12729
Ryan Sleevib8d7ea02018-05-07 20:01:0112730 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712731 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912732 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712733
[email protected]49639fa2011-12-20 23:22:4112734 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712735
bnc691fda62016-08-12 00:43:1612736 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712737
tfarina42834112016-09-22 13:38:2012738 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112739 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712740
12741 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112742 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812743
bnc691fda62016-08-12 00:43:1612744 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212745 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812746
wezca1070932016-05-26 20:30:5212747 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812748 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12749
12750 std::string response_data;
bnc691fda62016-08-12 00:43:1612751 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112752 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812753 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912754
12755 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612756 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912757 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712758}
12759
12760// Make sure that a dropped connection while draining the body for auth
12761// restart does the right thing.
bncd16676a2016-07-20 16:23:0112762TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712763 HttpRequestInfo request;
12764 request.method = "GET";
bncce36dca22015-04-21 22:11:2312765 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012766 request.traffic_annotation =
12767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712768
12769 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312770 MockWrite(
12771 "GET / HTTP/1.1\r\n"
12772 "Host: www.example.org\r\n"
12773 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712774 };
12775
12776 MockRead data_reads1[] = {
12777 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12778 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12779 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12780 MockRead("Content-Length: 14\r\n\r\n"),
12781 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612782 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712783 };
12784
Ryan Sleevib8d7ea02018-05-07 20:01:0112785 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712786 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712787
bnc691fda62016-08-12 00:43:1612788 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712789 // be issuing -- the final header line contains the credentials.
12790 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312791 MockWrite(
12792 "GET / HTTP/1.1\r\n"
12793 "Host: www.example.org\r\n"
12794 "Connection: keep-alive\r\n"
12795 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712796 };
12797
12798 // Lastly, the server responds with the actual content.
12799 MockRead data_reads2[] = {
12800 MockRead("HTTP/1.1 200 OK\r\n"),
12801 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12802 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612803 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712804 };
12805
Ryan Sleevib8d7ea02018-05-07 20:01:0112806 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712807 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912808 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712809
[email protected]49639fa2011-12-20 23:22:4112810 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712811
bnc691fda62016-08-12 00:43:1612812 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012813
tfarina42834112016-09-22 13:38:2012814 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112815 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712816
12817 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112818 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712819
bnc691fda62016-08-12 00:43:1612820 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212821 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812822 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712823
[email protected]49639fa2011-12-20 23:22:4112824 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712825
bnc691fda62016-08-12 00:43:1612826 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112827 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712828
12829 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112830 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712831
bnc691fda62016-08-12 00:43:1612832 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212833 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812834 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712835 EXPECT_EQ(100, response->headers->GetContentLength());
12836}
12837
12838// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112839TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Nicolas Arciniegad2013f92020-02-07 23:00:5612840 session_deps_.proxy_resolution_service =
12841 ConfiguredProxyResolutionService::CreateFixed(
12842 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712843
12844 HttpRequestInfo request;
12845 request.method = "GET";
bncce36dca22015-04-21 22:11:2312846 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012847 request.traffic_annotation =
12848 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712849
12850 MockRead proxy_reads[] = {
12851 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612852 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712853 };
12854
Ryan Sleevib8d7ea02018-05-07 20:01:0112855 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612856 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712857
[email protected]bb88e1d32013-05-03 23:11:0712858 session_deps_.socket_factory->AddSocketDataProvider(&data);
12859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712860
[email protected]49639fa2011-12-20 23:22:4112861 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712862
[email protected]bb88e1d32013-05-03 23:11:0712863 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712864
danakj1fd259a02016-04-16 03:17:0912865 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612866 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712867
tfarina42834112016-09-22 13:38:2012868 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712870
12871 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112872 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712873}
12874
bncd16676a2016-07-20 16:23:0112875TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612876 HttpRequestInfo request;
12877 request.method = "GET";
bncce36dca22015-04-21 22:11:2312878 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012879 request.traffic_annotation =
12880 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612881
danakj1fd259a02016-04-16 03:17:0912882 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612883 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712884
[email protected]e22e1362009-11-23 21:31:1212885 MockRead data_reads[] = {
12886 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612887 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212888 };
[email protected]9492e4a2010-02-24 00:58:4612889
Ryan Sleevib8d7ea02018-05-07 20:01:0112890 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712891 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612892
[email protected]49639fa2011-12-20 23:22:4112893 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612894
tfarina42834112016-09-22 13:38:2012895 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112896 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612897
robpercival214763f2016-07-01 23:27:0112898 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612899
bnc691fda62016-08-12 00:43:1612900 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212901 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612902
wezca1070932016-05-26 20:30:5212903 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612904 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12905
12906 std::string response_data;
bnc691fda62016-08-12 00:43:1612907 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112908 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212909}
12910
bncd16676a2016-07-20 16:23:0112911TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512912 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212913 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412914 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112915 UploadFileElementReader::ScopedOverridingContentLengthForTests
12916 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312917
danakj1fd259a02016-04-16 03:17:0912918 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912919 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412920 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712921 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212922 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712923
12924 HttpRequestInfo request;
12925 request.method = "POST";
bncce36dca22015-04-21 22:11:2312926 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712927 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012928 request.traffic_annotation =
12929 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712930
danakj1fd259a02016-04-16 03:17:0912931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612932 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312933
12934 MockRead data_reads[] = {
12935 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12936 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612937 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312938 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112939 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712940 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312941
[email protected]49639fa2011-12-20 23:22:4112942 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312943
tfarina42834112016-09-22 13:38:2012944 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112945 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312946
12947 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112948 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312949
bnc691fda62016-08-12 00:43:1612950 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212951 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312952
maksim.sisove869bf52016-06-23 17:11:5212953 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312954
Lei Zhang6dfdc9b12020-06-29 22:15:3112955 base::DeleteFile(temp_file_path);
[email protected]95d88ffe2010-02-04 21:25:3312956}
12957
bncd16676a2016-07-20 16:23:0112958TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512959 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212960 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612961 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812962 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12963 base::WriteFile(temp_file, temp_file_content.c_str(),
12964 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112965 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612966
danakj1fd259a02016-04-16 03:17:0912967 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912968 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412969 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712970 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212971 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712972
12973 HttpRequestInfo request;
12974 request.method = "POST";
bncce36dca22015-04-21 22:11:2312975 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712976 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012977 request.traffic_annotation =
12978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712979
[email protected]999dd8c2013-11-12 06:45:5412980 // If we try to upload an unreadable file, the transaction should fail.
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]6624b4622010-03-29 19:58:3612983
Ryan Sleevib8d7ea02018-05-07 20:01:0112984 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712985 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612986
[email protected]49639fa2011-12-20 23:22:4112987 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612988
tfarina42834112016-09-22 13:38:2012989 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112990 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612991
12992 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112993 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612994
Lei Zhang6dfdc9b12020-06-29 22:15:3112995 base::DeleteFile(temp_file);
[email protected]6624b4622010-03-29 19:58:3612996}
12997
bncd16676a2016-07-20 16:23:0112998TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312999 class FakeUploadElementReader : public UploadElementReader {
13000 public:
Chris Watkins7a41d3552017-12-01 02:13:2713001 FakeUploadElementReader() = default;
13002 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0313003
Matt Menkecc1d3a902018-02-05 18:27:3313004 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0313005
13006 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3313007 int Init(CompletionOnceCallback callback) override {
13008 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0313009 return ERR_IO_PENDING;
13010 }
avibf0746c2015-12-09 19:53:1413011 uint64_t GetContentLength() const override { return 0; }
13012 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2013013 int Read(IOBuffer* buf,
13014 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3313015 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0313016 return ERR_FAILED;
13017 }
13018
13019 private:
Matt Menkecc1d3a902018-02-05 18:27:3313020 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0313021 };
13022
13023 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0913024 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
13025 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2213026 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0313027
13028 HttpRequestInfo request;
13029 request.method = "POST";
bncce36dca22015-04-21 22:11:2313030 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0313031 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1013032 request.traffic_annotation =
13033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0313034
danakj1fd259a02016-04-16 03:17:0913035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813036 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913037 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0313038
13039 StaticSocketDataProvider data;
13040 session_deps_.socket_factory->AddSocketDataProvider(&data);
13041
13042 TestCompletionCallback callback;
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));
fdoray92e35a72016-06-10 15:54:5513045 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0313046
13047 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3313048 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
13049 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0313050
13051 // Return Init()'s result after the transaction gets destroyed.
13052 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3313053 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0313054}
13055
[email protected]aeefc9e82010-02-19 16:18:2713056// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0113057TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2713058 HttpRequestInfo request;
13059 request.method = "GET";
bncce36dca22015-04-21 22:11:2313060 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013061 request.traffic_annotation =
13062 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2713063
13064 // First transaction will request a resource and receive a Basic challenge
13065 // with realm="first_realm".
13066 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2313067 MockWrite(
13068 "GET / HTTP/1.1\r\n"
13069 "Host: www.example.org\r\n"
13070 "Connection: keep-alive\r\n"
13071 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713072 };
13073 MockRead data_reads1[] = {
13074 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13075 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13076 "\r\n"),
13077 };
13078
bnc691fda62016-08-12 00:43:1613079 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2713080 // for first_realm. The server will reject and provide a challenge with
13081 // second_realm.
13082 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2313083 MockWrite(
13084 "GET / HTTP/1.1\r\n"
13085 "Host: www.example.org\r\n"
13086 "Connection: keep-alive\r\n"
13087 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
13088 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713089 };
13090 MockRead data_reads2[] = {
13091 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13092 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
13093 "\r\n"),
13094 };
13095
13096 // This again fails, and goes back to first_realm. Make sure that the
13097 // entry is removed from cache.
13098 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2313099 MockWrite(
13100 "GET / HTTP/1.1\r\n"
13101 "Host: www.example.org\r\n"
13102 "Connection: keep-alive\r\n"
13103 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
13104 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713105 };
13106 MockRead data_reads3[] = {
13107 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13108 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13109 "\r\n"),
13110 };
13111
13112 // Try one last time (with the correct password) and get the resource.
13113 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2313114 MockWrite(
13115 "GET / HTTP/1.1\r\n"
13116 "Host: www.example.org\r\n"
13117 "Connection: keep-alive\r\n"
13118 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
13119 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713120 };
13121 MockRead data_reads4[] = {
13122 MockRead("HTTP/1.1 200 OK\r\n"
13123 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5013124 "Content-Length: 5\r\n"
13125 "\r\n"
13126 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2713127 };
13128
Ryan Sleevib8d7ea02018-05-07 20:01:0113129 StaticSocketDataProvider data1(data_reads1, data_writes1);
13130 StaticSocketDataProvider data2(data_reads2, data_writes2);
13131 StaticSocketDataProvider data3(data_reads3, data_writes3);
13132 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0713133 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13134 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13135 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13136 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2713137
[email protected]49639fa2011-12-20 23:22:4113138 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2713139
danakj1fd259a02016-04-16 03:17:0913140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613141 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5013142
[email protected]aeefc9e82010-02-19 16:18:2713143 // Issue the first request with Authorize headers. There should be a
13144 // password prompt for first_realm waiting to be filled in after the
13145 // transaction completes.
tfarina42834112016-09-22 13:38:2013146 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113147 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713148 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0113149 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613150 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213151 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813152 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213153 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413154 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313155 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413156 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913157 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713158
13159 // Issue the second request with an incorrect password. There should be a
13160 // password prompt for second_realm waiting to be filled in after the
13161 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4113162 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1613163 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
13164 callback2.callback());
robpercival214763f2016-07-01 23:27:0113165 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713166 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0113167 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613168 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213169 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813170 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213171 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413172 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313173 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413174 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913175 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713176
13177 // Issue the third request with another incorrect password. There should be
13178 // a password prompt for first_realm waiting to be filled in. If the password
13179 // prompt is not present, it indicates that the HttpAuthCacheEntry for
13180 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4113181 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1613182 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
13183 callback3.callback());
robpercival214763f2016-07-01 23:27:0113184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713185 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0113186 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613187 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213188 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813189 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213190 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413191 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313192 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413193 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913194 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713195
13196 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4113197 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1613198 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
13199 callback4.callback());
robpercival214763f2016-07-01 23:27:0113200 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713201 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0113202 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613203 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213204 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813205 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2713206}
13207
Bence Béky230ac612017-08-30 19:17:0813208// Regression test for https://crbug.com/754395.
13209TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
13210 MockRead data_reads[] = {
13211 MockRead("HTTP/1.1 200 OK\r\n"),
13212 MockRead(kAlternativeServiceHttpHeader),
13213 MockRead("\r\n"),
13214 MockRead("hello world"),
13215 MockRead(SYNCHRONOUS, OK),
13216 };
13217
13218 HttpRequestInfo request;
13219 request.method = "GET";
13220 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013221 request.traffic_annotation =
13222 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0813223
Ryan Sleevib8d7ea02018-05-07 20:01:0113224 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0813225 session_deps_.socket_factory->AddSocketDataProvider(&data);
13226
13227 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913228 ssl.ssl_info.cert =
13229 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13230 ASSERT_TRUE(ssl.ssl_info.cert);
13231 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0813232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13233
13234 TestCompletionCallback callback;
13235
13236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13237 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13238
13239 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13240 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13241
13242 url::SchemeHostPort test_server(request.url);
13243 HttpServerProperties* http_server_properties =
13244 session->http_server_properties();
13245 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913246 http_server_properties
13247 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13248 .empty());
Bence Béky230ac612017-08-30 19:17:0813249
13250 EXPECT_THAT(callback.WaitForResult(), IsOk());
13251
13252 const HttpResponseInfo* response = trans.GetResponseInfo();
13253 ASSERT_TRUE(response);
13254 ASSERT_TRUE(response->headers);
13255 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13256 EXPECT_FALSE(response->was_fetched_via_spdy);
13257 EXPECT_FALSE(response->was_alpn_negotiated);
13258
13259 std::string response_data;
13260 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13261 EXPECT_EQ("hello world", response_data);
13262
13263 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913264 http_server_properties
13265 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13266 .empty());
Bence Béky230ac612017-08-30 19:17:0813267}
13268
bncd16676a2016-07-20 16:23:0113269TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5213270 MockRead data_reads[] = {
13271 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313272 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213273 MockRead("\r\n"),
13274 MockRead("hello world"),
13275 MockRead(SYNCHRONOUS, OK),
13276 };
13277
13278 HttpRequestInfo request;
13279 request.method = "GET";
bncb26024382016-06-29 02:39:4513280 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013281 request.traffic_annotation =
13282 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213283
Ryan Sleevib8d7ea02018-05-07 20:01:0113284 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213285 session_deps_.socket_factory->AddSocketDataProvider(&data);
13286
bncb26024382016-06-29 02:39:4513287 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913288 ssl.ssl_info.cert =
13289 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13290 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13292
bncc958faa2015-07-31 18:14:5213293 TestCompletionCallback callback;
13294
danakj1fd259a02016-04-16 03:17:0913295 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613296 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213297
tfarina42834112016-09-22 13:38:2013298 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113299 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213300
bncb26024382016-06-29 02:39:4513301 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013302 HttpServerProperties* http_server_properties =
13303 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413304 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913305 http_server_properties
13306 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13307 .empty());
bncc958faa2015-07-31 18:14:5213308
robpercival214763f2016-07-01 23:27:0113309 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213310
bnc691fda62016-08-12 00:43:1613311 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213312 ASSERT_TRUE(response);
13313 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213314 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13315 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213316 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213317
13318 std::string response_data;
bnc691fda62016-08-12 00:43:1613319 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213320 EXPECT_EQ("hello world", response_data);
13321
zhongyic4de03032017-05-19 04:07:3413322 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913323 http_server_properties->GetAlternativeServiceInfos(test_server,
13324 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413325 ASSERT_EQ(1u, alternative_service_info_vector.size());
13326 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13327 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413328 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5213329}
13330
Matt Menke3233d8f22019-08-20 21:01:4913331TEST_F(HttpNetworkTransactionTest,
13332 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
13333 base::test::ScopedFeatureList feature_list;
13334 feature_list.InitWithFeatures(
13335 // enabled_features
13336 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
13337 // Need to partition connections by NetworkIsolationKey for
13338 // SpdySessionKeys to include NetworkIsolationKeys.
13339 features::kPartitionConnectionsByNetworkIsolationKey},
13340 // disabled_features
13341 {});
13342 // Since HttpServerProperties caches the feature value, have to create a new
13343 // one.
13344 session_deps_.http_server_properties =
13345 std::make_unique<HttpServerProperties>();
13346
Matt Menke4807a9a2020-11-21 00:14:4113347 const SchemefulSite kSite1(GURL("https://foo.test/"));
13348 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
13349 const SchemefulSite kSite2(GURL("https://bar.test/"));
13350 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
Matt Menke3233d8f22019-08-20 21:01:4913351
13352 MockRead data_reads[] = {
13353 MockRead("HTTP/1.1 200 OK\r\n"),
13354 MockRead(kAlternativeServiceHttpHeader),
13355 MockRead("\r\n"),
13356 MockRead("hello world"),
13357 MockRead(SYNCHRONOUS, OK),
13358 };
13359
13360 HttpRequestInfo request;
13361 request.method = "GET";
13362 request.url = GURL("https://www.example.org/");
13363 request.traffic_annotation =
13364 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13365 request.network_isolation_key = kNetworkIsolationKey1;
13366
13367 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
13368 session_deps_.socket_factory->AddSocketDataProvider(&data);
13369
13370 SSLSocketDataProvider ssl(ASYNC, OK);
13371 ssl.ssl_info.cert =
13372 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13373 ASSERT_TRUE(ssl.ssl_info.cert);
13374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13375
13376 TestCompletionCallback callback;
13377
13378 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13379 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13380
13381 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13383
13384 url::SchemeHostPort test_server(request.url);
13385 HttpServerProperties* http_server_properties =
13386 session->http_server_properties();
13387 EXPECT_TRUE(
13388 http_server_properties
13389 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
13390 .empty());
13391
13392 EXPECT_THAT(callback.WaitForResult(), IsOk());
13393
13394 const HttpResponseInfo* response = trans.GetResponseInfo();
13395 ASSERT_TRUE(response);
13396 ASSERT_TRUE(response->headers);
13397 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13398 EXPECT_FALSE(response->was_fetched_via_spdy);
13399 EXPECT_FALSE(response->was_alpn_negotiated);
13400
13401 std::string response_data;
13402 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13403 EXPECT_EQ("hello world", response_data);
13404
13405 AlternativeServiceInfoVector alternative_service_info_vector =
13406 http_server_properties->GetAlternativeServiceInfos(test_server,
13407 kNetworkIsolationKey1);
13408 ASSERT_EQ(1u, alternative_service_info_vector.size());
13409 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13410 EXPECT_EQ(alternative_service,
13411 alternative_service_info_vector[0].alternative_service());
13412
13413 // Make sure the alternative service information is only associated with
13414 // kNetworkIsolationKey1.
13415 EXPECT_TRUE(
13416 http_server_properties
13417 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13418 .empty());
13419 EXPECT_TRUE(
13420 http_server_properties
13421 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13422 .empty());
13423}
13424
bnce3dd56f2016-06-01 10:37:1113425// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113426TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113427 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113428 MockRead data_reads[] = {
13429 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313430 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113431 MockRead("\r\n"),
13432 MockRead("hello world"),
13433 MockRead(SYNCHRONOUS, OK),
13434 };
13435
13436 HttpRequestInfo request;
13437 request.method = "GET";
13438 request.url = GURL("http://www.example.org/");
13439 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013440 request.traffic_annotation =
13441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113442
Ryan Sleevib8d7ea02018-05-07 20:01:0113443 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113444 session_deps_.socket_factory->AddSocketDataProvider(&data);
13445
13446 TestCompletionCallback callback;
13447
13448 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613449 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113450
13451 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013452 HttpServerProperties* http_server_properties =
13453 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413454 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913455 http_server_properties
13456 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13457 .empty());
bnce3dd56f2016-06-01 10:37:1113458
tfarina42834112016-09-22 13:38:2013459 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113460 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13461 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113462
bnc691fda62016-08-12 00:43:1613463 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113464 ASSERT_TRUE(response);
13465 ASSERT_TRUE(response->headers);
13466 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13467 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213468 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113469
13470 std::string response_data;
bnc691fda62016-08-12 00:43:1613471 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113472 EXPECT_EQ("hello world", response_data);
13473
zhongyic4de03032017-05-19 04:07:3413474 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913475 http_server_properties
13476 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13477 .empty());
bnce3dd56f2016-06-01 10:37:1113478}
13479
bnca86731e2017-04-17 12:31:2813480// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513481// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113482TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513483 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813484 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513485
bnc8bef8da22016-05-30 01:28:2513486 HttpRequestInfo request;
13487 request.method = "GET";
bncb26024382016-06-29 02:39:4513488 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513489 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013490 request.traffic_annotation =
13491 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513492
13493 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13494 StaticSocketDataProvider first_data;
13495 first_data.set_connect_data(mock_connect);
13496 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513497 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613498 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513499 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513500
13501 MockRead data_reads[] = {
13502 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13503 MockRead(ASYNC, OK),
13504 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113505 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513506 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13507
13508 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13509
bnc525e175a2016-06-20 12:36:4013510 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513511 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113512 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13513 444);
bnc8bef8da22016-05-30 01:28:2513514 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113515 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713516 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13517 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513518
bnc691fda62016-08-12 00:43:1613519 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513520 TestCompletionCallback callback;
13521
tfarina42834112016-09-22 13:38:2013522 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513523 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113524 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513525}
13526
bnce3dd56f2016-06-01 10:37:1113527// Regression test for https://crbug.com/615497:
13528// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113529TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113530 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113531 HttpRequestInfo request;
13532 request.method = "GET";
13533 request.url = GURL("http://www.example.org/");
13534 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013535 request.traffic_annotation =
13536 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113537
13538 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13539 StaticSocketDataProvider first_data;
13540 first_data.set_connect_data(mock_connect);
13541 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13542
13543 MockRead data_reads[] = {
13544 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13545 MockRead(ASYNC, OK),
13546 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113547 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113548 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13549
13550 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13551
bnc525e175a2016-06-20 12:36:4013552 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113553 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113554 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113555 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113556 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713557 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13558 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113559
bnc691fda62016-08-12 00:43:1613560 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113561 TestCompletionCallback callback;
13562
tfarina42834112016-09-22 13:38:2013563 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113564 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113565 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113566}
13567
bncd16676a2016-07-20 16:23:0113568TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813569 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913570 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013571 HttpServerProperties* http_server_properties =
13572 session->http_server_properties();
bncb26024382016-06-29 02:39:4513573 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113574 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813575 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113576 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713577 test_server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813578 session->context().quic_context->params()->supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913579 EXPECT_EQ(1u,
13580 http_server_properties
13581 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13582 .size());
bnc4f575852015-10-14 18:35:0813583
13584 // Send a clear header.
13585 MockRead data_reads[] = {
13586 MockRead("HTTP/1.1 200 OK\r\n"),
13587 MockRead("Alt-Svc: clear\r\n"),
13588 MockRead("\r\n"),
13589 MockRead("hello world"),
13590 MockRead(SYNCHRONOUS, OK),
13591 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113592 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813593 session_deps_.socket_factory->AddSocketDataProvider(&data);
13594
bncb26024382016-06-29 02:39:4513595 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913596 ssl.ssl_info.cert =
13597 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13598 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513599 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13600
bnc4f575852015-10-14 18:35:0813601 HttpRequestInfo request;
13602 request.method = "GET";
bncb26024382016-06-29 02:39:4513603 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013604 request.traffic_annotation =
13605 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813606
13607 TestCompletionCallback callback;
13608
bnc691fda62016-08-12 00:43:1613609 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813610
tfarina42834112016-09-22 13:38:2013611 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113612 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813613
bnc691fda62016-08-12 00:43:1613614 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213615 ASSERT_TRUE(response);
13616 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813617 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13618 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213619 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813620
13621 std::string response_data;
bnc691fda62016-08-12 00:43:1613622 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813623 EXPECT_EQ("hello world", response_data);
13624
zhongyic4de03032017-05-19 04:07:3413625 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913626 http_server_properties
13627 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13628 .empty());
bnc4f575852015-10-14 18:35:0813629}
13630
bncd16676a2016-07-20 16:23:0113631TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213632 MockRead data_reads[] = {
13633 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313634 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13635 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213636 MockRead("hello world"),
13637 MockRead(SYNCHRONOUS, OK),
13638 };
13639
13640 HttpRequestInfo request;
13641 request.method = "GET";
bncb26024382016-06-29 02:39:4513642 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013643 request.traffic_annotation =
13644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213645
Ryan Sleevib8d7ea02018-05-07 20:01:0113646 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213647 session_deps_.socket_factory->AddSocketDataProvider(&data);
13648
bncb26024382016-06-29 02:39:4513649 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913650 ssl.ssl_info.cert =
13651 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13652 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13654
bncc958faa2015-07-31 18:14:5213655 TestCompletionCallback callback;
13656
danakj1fd259a02016-04-16 03:17:0913657 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613658 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213659
tfarina42834112016-09-22 13:38:2013660 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113661 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213662
bncb26024382016-06-29 02:39:4513663 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013664 HttpServerProperties* http_server_properties =
13665 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413666 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913667 http_server_properties
13668 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13669 .empty());
bncc958faa2015-07-31 18:14:5213670
robpercival214763f2016-07-01 23:27:0113671 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213672
bnc691fda62016-08-12 00:43:1613673 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213674 ASSERT_TRUE(response);
13675 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213676 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13677 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213678 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213679
13680 std::string response_data;
bnc691fda62016-08-12 00:43:1613681 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213682 EXPECT_EQ("hello world", response_data);
13683
zhongyic4de03032017-05-19 04:07:3413684 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913685 http_server_properties->GetAlternativeServiceInfos(test_server,
13686 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413687 ASSERT_EQ(2u, alternative_service_info_vector.size());
13688
13689 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13690 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413691 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413692 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13693 1234);
13694 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413695 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213696}
13697
bncd16676a2016-07-20 16:23:0113698TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613699 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213700 HostPortPair alternative("alternative.example.org", 443);
13701 std::string origin_url = "https://origin.example.org:443";
13702 std::string alternative_url = "https://alternative.example.org:443";
13703
13704 // Negotiate HTTP/1.1 with alternative.example.org.
13705 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613706 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213707 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13708
13709 // HTTP/1.1 data for request.
13710 MockWrite http_writes[] = {
13711 MockWrite("GET / HTTP/1.1\r\n"
13712 "Host: alternative.example.org\r\n"
13713 "Connection: keep-alive\r\n\r\n"),
13714 };
13715
13716 MockRead http_reads[] = {
13717 MockRead("HTTP/1.1 200 OK\r\n"
13718 "Content-Type: text/html; charset=iso-8859-1\r\n"
13719 "Content-Length: 40\r\n\r\n"
13720 "first HTTP/1.1 response from alternative"),
13721 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113722 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213723 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13724
13725 StaticSocketDataProvider data_refused;
13726 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13727 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13728
zhongyi3d4a55e72016-04-22 20:36:4613729 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913730 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013731 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213732 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113733 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213734 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113735 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713736 server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813737 DefaultSupportedQuicVersions());
zhongyi48704c182015-12-07 07:52:0213738 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513739 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13740 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213741
zhongyi48704c182015-12-07 07:52:0213742 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613743 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213744 request.method = "GET";
13745 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013746 request.traffic_annotation =
13747 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13748
zhongyi48704c182015-12-07 07:52:0213749 TestCompletionCallback callback;
13750 NetErrorDetails details;
13751 EXPECT_FALSE(details.quic_broken);
13752
tfarina42834112016-09-22 13:38:2013753 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613754 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213755 EXPECT_TRUE(details.quic_broken);
13756}
13757
bncd16676a2016-07-20 16:23:0113758TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613759 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213760 HostPortPair alternative1("alternative1.example.org", 443);
13761 HostPortPair alternative2("alternative2.example.org", 443);
13762 std::string origin_url = "https://origin.example.org:443";
13763 std::string alternative_url1 = "https://alternative1.example.org:443";
13764 std::string alternative_url2 = "https://alternative2.example.org:443";
13765
13766 // Negotiate HTTP/1.1 with alternative1.example.org.
13767 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613768 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213769 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13770
13771 // HTTP/1.1 data for request.
13772 MockWrite http_writes[] = {
13773 MockWrite("GET / HTTP/1.1\r\n"
13774 "Host: alternative1.example.org\r\n"
13775 "Connection: keep-alive\r\n\r\n"),
13776 };
13777
13778 MockRead http_reads[] = {
13779 MockRead("HTTP/1.1 200 OK\r\n"
13780 "Content-Type: text/html; charset=iso-8859-1\r\n"
13781 "Content-Length: 40\r\n\r\n"
13782 "first HTTP/1.1 response from alternative1"),
13783 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113784 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213785 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13786
13787 StaticSocketDataProvider data_refused;
13788 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13789 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13790
danakj1fd259a02016-04-16 03:17:0913791 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013792 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213793 session->http_server_properties();
13794
zhongyi3d4a55e72016-04-22 20:36:4613795 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213796 AlternativeServiceInfoVector alternative_service_info_vector;
13797 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13798
bnc3472afd2016-11-17 15:27:2113799 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113800 alternative_service_info_vector.push_back(
13801 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13802 alternative_service1, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813803 session->context().quic_context->params()->supported_versions));
bnc3472afd2016-11-17 15:27:2113804 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113805 alternative_service_info_vector.push_back(
13806 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13807 alternative_service2, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813808 session->context().quic_context->params()->supported_versions));
zhongyi48704c182015-12-07 07:52:0213809
13810 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913811 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213812
13813 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513814 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13815 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913816 EXPECT_EQ(2u, http_server_properties
13817 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13818 .size());
zhongyi48704c182015-12-07 07:52:0213819
zhongyi48704c182015-12-07 07:52:0213820 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613821 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213822 request.method = "GET";
13823 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013824 request.traffic_annotation =
13825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13826
zhongyi48704c182015-12-07 07:52:0213827 TestCompletionCallback callback;
13828 NetErrorDetails details;
13829 EXPECT_FALSE(details.quic_broken);
13830
tfarina42834112016-09-22 13:38:2013831 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613832 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213833 EXPECT_FALSE(details.quic_broken);
13834}
13835
bncd16676a2016-07-20 16:23:0113836TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213837 HttpRequestInfo request;
13838 request.method = "GET";
bncb26024382016-06-29 02:39:4513839 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013840 request.traffic_annotation =
13841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213842
[email protected]d973e99a2012-02-17 21:02:3613843 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213844 StaticSocketDataProvider first_data;
13845 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713846 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513847 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613848 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213850
13851 MockRead data_reads[] = {
13852 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13853 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613854 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213855 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113856 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713857 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213858
danakj1fd259a02016-04-16 03:17:0913859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213860
bnc525e175a2016-06-20 12:36:4013861 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313862 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613863 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113864 // Port must be < 1024, or the header will be ignored (since initial port was
13865 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113866 // Port is ignored by MockConnect anyway.
13867 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13868 666);
bnc7dc7e1b42015-07-28 14:43:1213869 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113870 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713871 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213872
bnc691fda62016-08-12 00:43:1613873 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113874 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213875
tfarina42834112016-09-22 13:38:2013876 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13878 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213879
bnc691fda62016-08-12 00:43:1613880 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213881 ASSERT_TRUE(response);
13882 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213883 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13884
13885 std::string response_data;
bnc691fda62016-08-12 00:43:1613886 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213887 EXPECT_EQ("hello world", response_data);
13888
zhongyic4de03032017-05-19 04:07:3413889 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913890 http_server_properties->GetAlternativeServiceInfos(server,
13891 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413892 ASSERT_EQ(1u, alternative_service_info_vector.size());
13893 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413894 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513895 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13896 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213897}
13898
bnc55ff9da2015-08-19 18:42:3513899// Ensure that we are not allowed to redirect traffic via an alternate protocol
13900// to an unrestricted (port >= 1024) when the original traffic was on a
13901// restricted port (port < 1024). Ensure that we can redirect in all other
13902// cases.
bncd16676a2016-07-20 16:23:0113903TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113904 HttpRequestInfo restricted_port_request;
13905 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513906 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113907 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013908 restricted_port_request.traffic_annotation =
13909 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113910
[email protected]d973e99a2012-02-17 21:02:3613911 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113912 StaticSocketDataProvider first_data;
13913 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713914 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113915
13916 MockRead data_reads[] = {
13917 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13918 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613919 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113920 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113921 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713922 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513923 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613924 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513925 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113926
danakj1fd259a02016-04-16 03:17:0913927 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113928
bnc525e175a2016-06-20 12:36:4013929 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313930 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113931 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113932 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13933 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213934 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113935 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713936 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13937 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113938
bnc691fda62016-08-12 00:43:1613939 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113940 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113941
tfarina42834112016-09-22 13:38:2013942 int rv = trans.Start(&restricted_port_request, callback.callback(),
13943 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113944 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113945 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113946 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913947}
[email protected]3912662a32011-10-04 00:51:1113948
bnc55ff9da2015-08-19 18:42:3513949// Ensure that we are allowed to redirect traffic via an alternate protocol to
13950// an unrestricted (port >= 1024) when the original traffic was on a restricted
13951// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113952TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713953 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913954
13955 HttpRequestInfo restricted_port_request;
13956 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513957 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913958 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013959 restricted_port_request.traffic_annotation =
13960 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913961
13962 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13963 StaticSocketDataProvider first_data;
13964 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713965 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913966
13967 MockRead data_reads[] = {
13968 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13969 MockRead("hello world"),
13970 MockRead(ASYNC, OK),
13971 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113972 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713973 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513974 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613975 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513976 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913977
danakj1fd259a02016-04-16 03:17:0913978 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913979
bnc525e175a2016-06-20 12:36:4013980 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913981 session->http_server_properties();
13982 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113983 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13984 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213985 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113986 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713987 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13988 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913989
bnc691fda62016-08-12 00:43:1613990 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913991 TestCompletionCallback callback;
13992
tfarina42834112016-09-22 13:38:2013993 EXPECT_EQ(ERR_IO_PENDING,
13994 trans.Start(&restricted_port_request, callback.callback(),
13995 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913996 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113997 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113998}
13999
bnc55ff9da2015-08-19 18:42:3514000// Ensure that we are not allowed to redirect traffic via an alternate protocol
14001// to an unrestricted (port >= 1024) when the original traffic was on a
14002// restricted port (port < 1024). Ensure that we can redirect in all other
14003// cases.
bncd16676a2016-07-20 16:23:0114004TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1114005 HttpRequestInfo restricted_port_request;
14006 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514007 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1114008 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014009 restricted_port_request.traffic_annotation =
14010 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114011
[email protected]d973e99a2012-02-17 21:02:3614012 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114013 StaticSocketDataProvider first_data;
14014 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714015 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114016
14017 MockRead data_reads[] = {
14018 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14019 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614020 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114021 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114022 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714023 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1114024
bncb26024382016-06-29 02:39:4514025 SSLSocketDataProvider ssl(ASYNC, OK);
14026 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14027
danakj1fd259a02016-04-16 03:17:0914028 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114029
bnc525e175a2016-06-20 12:36:4014030 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314031 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114032 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114033 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14034 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214035 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114036 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714037 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
14038 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114039
bnc691fda62016-08-12 00:43:1614040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114041 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114042
tfarina42834112016-09-22 13:38:2014043 int rv = trans.Start(&restricted_port_request, callback.callback(),
14044 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114045 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114046 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0114047 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114048}
14049
bnc55ff9da2015-08-19 18:42:3514050// Ensure that we are not allowed to redirect traffic via an alternate protocol
14051// to an unrestricted (port >= 1024) when the original traffic was on a
14052// restricted port (port < 1024). Ensure that we can redirect in all other
14053// cases.
bncd16676a2016-07-20 16:23:0114054TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1114055 HttpRequestInfo unrestricted_port_request;
14056 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514057 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114058 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014059 unrestricted_port_request.traffic_annotation =
14060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114061
[email protected]d973e99a2012-02-17 21:02:3614062 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114063 StaticSocketDataProvider first_data;
14064 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714065 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114066
14067 MockRead data_reads[] = {
14068 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14069 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614070 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114071 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114072 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714073 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4514074 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614075 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514076 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1114077
danakj1fd259a02016-04-16 03:17:0914078 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114079
bnc525e175a2016-06-20 12:36:4014080 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314081 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114082 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114083 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14084 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214085 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114086 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714087 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14088 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114089
bnc691fda62016-08-12 00:43:1614090 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114091 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114092
bnc691fda62016-08-12 00:43:1614093 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014094 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114095 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114096 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0114097 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114098}
14099
bnc55ff9da2015-08-19 18:42:3514100// Ensure that we are not allowed to redirect traffic via an alternate protocol
14101// to an unrestricted (port >= 1024) when the original traffic was on a
14102// restricted port (port < 1024). Ensure that we can redirect in all other
14103// cases.
bncd16676a2016-07-20 16:23:0114104TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1114105 HttpRequestInfo unrestricted_port_request;
14106 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514107 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114108 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014109 unrestricted_port_request.traffic_annotation =
14110 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114111
[email protected]d973e99a2012-02-17 21:02:3614112 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114113 StaticSocketDataProvider first_data;
14114 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714115 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114116
14117 MockRead data_reads[] = {
14118 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14119 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614120 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114121 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114122 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714123 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1114124
bncb26024382016-06-29 02:39:4514125 SSLSocketDataProvider ssl(ASYNC, OK);
14126 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14127
danakj1fd259a02016-04-16 03:17:0914128 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114129
bnc525e175a2016-06-20 12:36:4014130 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314131 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2214132 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2114133 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14134 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214135 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114136 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714137 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14138 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114139
bnc691fda62016-08-12 00:43:1614140 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114141 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114142
bnc691fda62016-08-12 00:43:1614143 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014144 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114145 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114146 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0114147 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114148}
14149
bnc55ff9da2015-08-19 18:42:3514150// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2114151// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
14152// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0114153TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0214154 HttpRequestInfo request;
14155 request.method = "GET";
bncce36dca22015-04-21 22:11:2314156 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014157 request.traffic_annotation =
14158 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0214159
14160 // The alternate protocol request will error out before we attempt to connect,
14161 // so only the standard HTTP request will try to connect.
14162 MockRead data_reads[] = {
14163 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14164 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614165 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0214166 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114167 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714168 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0214169
danakj1fd259a02016-04-16 03:17:0914170 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0214171
bnc525e175a2016-06-20 12:36:4014172 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0214173 session->http_server_properties();
14174 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2114175 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14176 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1214177 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114178 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714179 url::SchemeHostPort(request.url), NetworkIsolationKey(),
14180 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0214181
bnc691fda62016-08-12 00:43:1614182 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0214183 TestCompletionCallback callback;
14184
tfarina42834112016-09-22 13:38:2014185 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114186 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0214187 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0114188 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214189
bnc691fda62016-08-12 00:43:1614190 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214191 ASSERT_TRUE(response);
14192 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0214193 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14194
14195 std::string response_data;
bnc691fda62016-08-12 00:43:1614196 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214197 EXPECT_EQ("hello world", response_data);
14198}
14199
bncd16676a2016-07-20 16:23:0114200TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5414201 HttpRequestInfo request;
14202 request.method = "GET";
bncb26024382016-06-29 02:39:4514203 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014204 request.traffic_annotation =
14205 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414206
14207 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214208 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314209 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214210 MockRead("\r\n"),
14211 MockRead("hello world"),
14212 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14213 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5414214
Ryan Sleevib8d7ea02018-05-07 20:01:0114215 StaticSocketDataProvider first_transaction(data_reads,
14216 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714217 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514218 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614219 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514220 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414221
bnc032658ba2016-09-26 18:17:1514222 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414223
Ryan Hamilton0239aac2018-05-19 00:03:1314224 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514225 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114226 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414227
Raul Tambre94493c652019-03-11 17:18:3514228 spdy::SpdySerializedFrame resp(
14229 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314230 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414231 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114232 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414233 };
14234
Ryan Sleevib8d7ea02018-05-07 20:01:0114235 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714236 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414237
[email protected]d973e99a2012-02-17 21:02:3614238 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114239 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514240 hanging_non_alternate_protocol_socket.set_connect_data(
14241 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714242 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514243 &hanging_non_alternate_protocol_socket);
14244
[email protected]49639fa2011-12-20 23:22:4114245 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414246
danakj1fd259a02016-04-16 03:17:0914247 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814248 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914249 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414250
tfarina42834112016-09-22 13:38:2014251 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114252 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14253 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414254
14255 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214256 ASSERT_TRUE(response);
14257 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414258 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14259
14260 std::string response_data;
robpercival214763f2016-07-01 23:27:0114261 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414262 EXPECT_EQ("hello world", response_data);
14263
bnc87dcefc2017-05-25 12:47:5814264 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914265 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414266
tfarina42834112016-09-22 13:38:2014267 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114268 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14269 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414270
14271 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214272 ASSERT_TRUE(response);
14273 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214274 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314275 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214276 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414277
robpercival214763f2016-07-01 23:27:0114278 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414279 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5414280}
14281
bncd16676a2016-07-20 16:23:0114282TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5514283 HttpRequestInfo request;
14284 request.method = "GET";
bncb26024382016-06-29 02:39:4514285 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014286 request.traffic_annotation =
14287 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514288
bncb26024382016-06-29 02:39:4514289 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5514290 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214291 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314292 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214293 MockRead("\r\n"),
14294 MockRead("hello world"),
14295 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14296 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514297 };
14298
Ryan Sleevib8d7ea02018-05-07 20:01:0114299 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4514300 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5514301
bncb26024382016-06-29 02:39:4514302 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914303 ssl_http11.ssl_info.cert =
14304 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14305 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4514306 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
14307
14308 // Second transaction starts an alternative and a non-alternative Job.
14309 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3614310 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114311 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1814312 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1814313 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
14314
Ryan Sleevib8d7ea02018-05-07 20:01:0114315 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1814316 hanging_socket2.set_connect_data(never_finishing_connect);
14317 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5514318
bncb26024382016-06-29 02:39:4514319 // Third transaction starts an alternative and a non-alternative job.
14320 // The non-alternative job hangs, but the alternative one succeeds.
14321 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1314322 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4514323 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1314324 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4514325 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5514326 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4114327 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5514328 };
Raul Tambre94493c652019-03-11 17:18:3514329 spdy::SpdySerializedFrame resp1(
14330 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314331 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3514332 spdy::SpdySerializedFrame resp2(
14333 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1314334 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5514335 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114336 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
14337 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1314338 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5514339 };
14340
Ryan Sleevib8d7ea02018-05-07 20:01:0114341 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714342 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5514343
bnc032658ba2016-09-26 18:17:1514344 AddSSLSocketData();
bncb26024382016-06-29 02:39:4514345
Ryan Sleevib8d7ea02018-05-07 20:01:0114346 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1814347 hanging_socket3.set_connect_data(never_finishing_connect);
14348 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5514349
danakj1fd259a02016-04-16 03:17:0914350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4114351 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5014352 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514353
tfarina42834112016-09-22 13:38:2014354 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14356 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514357
14358 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5214359 ASSERT_TRUE(response);
14360 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514361 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14362
14363 std::string response_data;
robpercival214763f2016-07-01 23:27:0114364 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514365 EXPECT_EQ("hello world", response_data);
14366
[email protected]49639fa2011-12-20 23:22:4114367 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5014368 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014369 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514371
[email protected]49639fa2011-12-20 23:22:4114372 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5014373 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014374 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114375 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514376
robpercival214763f2016-07-01 23:27:0114377 EXPECT_THAT(callback2.WaitForResult(), IsOk());
14378 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514379
14380 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5214381 ASSERT_TRUE(response);
14382 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214383 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514384 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214385 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114386 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514387 EXPECT_EQ("hello!", response_data);
14388
14389 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5214390 ASSERT_TRUE(response);
14391 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214392 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514393 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214394 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114395 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514396 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5514397}
14398
bncd16676a2016-07-20 16:23:0114399TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5314400 session_deps_.host_resolver->set_synchronous_mode(true);
14401
[email protected]2d6728692011-03-12 01:39:5514402 HttpRequestInfo request;
14403 request.method = "GET";
bncb26024382016-06-29 02:39:4514404 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014405 request.traffic_annotation =
14406 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514407
14408 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214409 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314410 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214411 MockRead("\r\n"),
14412 MockRead("hello world"),
14413 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14414 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514415 };
14416
Ryan Sleevib8d7ea02018-05-07 20:01:0114417 StaticSocketDataProvider first_transaction(data_reads,
14418 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714419 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5514420
[email protected]8ddf8322012-02-23 18:08:0614421 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914422 ssl.ssl_info.cert =
14423 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14424 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714425 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514426
[email protected]d973e99a2012-02-17 21:02:3614427 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114428 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514429 hanging_alternate_protocol_socket.set_connect_data(
14430 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714431 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514432 &hanging_alternate_protocol_socket);
14433
bncb26024382016-06-29 02:39:4514434 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114435 StaticSocketDataProvider second_transaction(data_reads,
14436 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814437 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514438 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514439
[email protected]49639fa2011-12-20 23:22:4114440 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514441
danakj1fd259a02016-04-16 03:17:0914442 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814443 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914444 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514445
tfarina42834112016-09-22 13:38:2014446 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114447 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14448 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514449
14450 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214451 ASSERT_TRUE(response);
14452 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514453 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14454
14455 std::string response_data;
robpercival214763f2016-07-01 23:27:0114456 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514457 EXPECT_EQ("hello world", response_data);
14458
bnc87dcefc2017-05-25 12:47:5814459 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914460 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514461
tfarina42834112016-09-22 13:38:2014462 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14464 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514465
14466 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214467 ASSERT_TRUE(response);
14468 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14470 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214471 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514472
robpercival214763f2016-07-01 23:27:0114473 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514474 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514475}
14476
bnc2e884782016-08-11 19:45:1914477// Test that proxy is resolved using the origin url,
14478// regardless of the alternative server.
14479TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14480 // Configure proxy to bypass www.example.org, which is the origin URL.
14481 ProxyConfig proxy_config;
14482 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14483 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914484 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14485 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914486
14487 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914488 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914489 &capturing_proxy_resolver);
14490
Matt Muellerd9342e3a2019-11-26 01:41:1414491 RecordingTestNetLog net_log;
bnc2e884782016-08-11 19:45:1914492
Bence Béky53a5aef2018-03-29 21:54:1214493 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614494 std::make_unique<ConfiguredProxyResolutionService>(
Bence Béky53a5aef2018-03-29 21:54:1214495 std::move(proxy_config_service), std::move(proxy_resolver_factory),
Eric Roman3be01ba2020-04-03 21:37:0914496 &net_log, /*quick_check_enabled=*/true);
bnc2e884782016-08-11 19:45:1914497
14498 session_deps_.net_log = &net_log;
14499
14500 // Configure alternative service with a hostname that is not bypassed by the
14501 // proxy.
14502 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14503 HttpServerProperties* http_server_properties =
14504 session->http_server_properties();
14505 url::SchemeHostPort server("https", "www.example.org", 443);
14506 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114507 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914508 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114509 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714510 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914511
14512 // Non-alternative job should hang.
14513 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114514 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914515 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14516 session_deps_.socket_factory->AddSocketDataProvider(
14517 &hanging_alternate_protocol_socket);
14518
bnc032658ba2016-09-26 18:17:1514519 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914520
14521 HttpRequestInfo request;
14522 request.method = "GET";
14523 request.url = GURL("https://www.example.org/");
14524 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014525 request.traffic_annotation =
14526 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914527
Ryan Hamilton0239aac2018-05-19 00:03:1314528 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914529 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14530
14531 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14532
Ryan Hamilton0239aac2018-05-19 00:03:1314533 spdy::SpdySerializedFrame resp(
14534 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14535 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914536 MockRead spdy_reads[] = {
14537 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14538 };
14539
Ryan Sleevib8d7ea02018-05-07 20:01:0114540 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914541 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14542
14543 TestCompletionCallback callback;
14544
14545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14546
tfarina42834112016-09-22 13:38:2014547 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914548 EXPECT_THAT(callback.GetResult(rv), IsOk());
14549
14550 const HttpResponseInfo* response = trans.GetResponseInfo();
14551 ASSERT_TRUE(response);
14552 ASSERT_TRUE(response->headers);
14553 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14554 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214555 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914556
14557 std::string response_data;
14558 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14559 EXPECT_EQ("hello!", response_data);
14560
14561 // Origin host bypasses proxy, no resolution should have happened.
Matt Menke8045afd2019-11-14 20:31:1914562 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
bnc2e884782016-08-11 19:45:1914563}
14564
bncd16676a2016-07-20 16:23:0114565TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114566 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214567 proxy_config.set_auto_detect(true);
14568 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114569
sammc5dd160c2015-04-02 02:43:1314570 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914571 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614572 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4914573 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14574 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14575 std::make_unique<CapturingProxyResolverFactory>(
14576 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:0914577 nullptr, /*quick_check_enabled=*/true);
Matt Muellerd9342e3a2019-11-26 01:41:1414578 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714579 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114580
14581 HttpRequestInfo request;
14582 request.method = "GET";
bncb26024382016-06-29 02:39:4514583 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014584 request.traffic_annotation =
14585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114586
14587 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214588 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314589 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214590 MockRead("\r\n"),
14591 MockRead("hello world"),
14592 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14593 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114594 };
14595
Ryan Sleevib8d7ea02018-05-07 20:01:0114596 StaticSocketDataProvider first_transaction(data_reads,
14597 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714598 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514599 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614600 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514601 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114602
bnc032658ba2016-09-26 18:17:1514603 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114604
Ryan Hamilton0239aac2018-05-19 00:03:1314605 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514606 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114607 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314608 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514609 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14610 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314611 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114612 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114613 };
14614
[email protected]d911f1b2010-05-05 22:39:4214615 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14616
Raul Tambre94493c652019-03-11 17:18:3514617 spdy::SpdySerializedFrame resp(
14618 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314619 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114620 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114621 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14622 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114623 };
14624
Ryan Sleevib8d7ea02018-05-07 20:01:0114625 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714626 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114627
[email protected]d973e99a2012-02-17 21:02:3614628 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114629 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514630 hanging_non_alternate_protocol_socket.set_connect_data(
14631 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714632 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514633 &hanging_non_alternate_protocol_socket);
14634
[email protected]49639fa2011-12-20 23:22:4114635 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114636
danakj1fd259a02016-04-16 03:17:0914637 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814638 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914639 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114640
tfarina42834112016-09-22 13:38:2014641 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114642 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14643 EXPECT_THAT(callback.WaitForResult(), IsOk());
14644
14645 const HttpResponseInfo* response = trans->GetResponseInfo();
14646 ASSERT_TRUE(response);
14647 ASSERT_TRUE(response->headers);
14648 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14649 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214650 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114651
14652 std::string response_data;
14653 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14654 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114655
bnc87dcefc2017-05-25 12:47:5814656 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914657 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114658
tfarina42834112016-09-22 13:38:2014659 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14661 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114662
mmenkea2dcd3bf2016-08-16 21:49:4114663 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214664 ASSERT_TRUE(response);
14665 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214666 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314667 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214668 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114669
robpercival214763f2016-07-01 23:27:0114670 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114671 EXPECT_EQ("hello!", response_data);
Matt Menke8045afd2019-11-14 20:31:1914672 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
bncb26024382016-06-29 02:39:4514673 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914674 capturing_proxy_resolver.lookup_info()[0].url.spec());
bncce36dca22015-04-21 22:11:2314675 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914676 capturing_proxy_resolver.lookup_info()[1].url.spec());
[email protected]631f1322010-04-30 17:59:1114677
[email protected]029c83b62013-01-24 05:28:2014678 LoadTimingInfo load_timing_info;
14679 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14680 TestLoadTimingNotReusedWithPac(load_timing_info,
14681 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114682}
[email protected]631f1322010-04-30 17:59:1114683
bncd16676a2016-07-20 16:23:0114684TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814685 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414686 HttpRequestInfo request;
14687 request.method = "GET";
bncb26024382016-06-29 02:39:4514688 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014689 request.traffic_annotation =
14690 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414691
14692 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214693 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314694 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214695 MockRead("\r\n"),
14696 MockRead("hello world"),
14697 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414698 };
14699
Ryan Sleevib8d7ea02018-05-07 20:01:0114700 StaticSocketDataProvider first_transaction(data_reads,
14701 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714702 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514703 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614704 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414706
bnc032658ba2016-09-26 18:17:1514707 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414708
Ryan Hamilton0239aac2018-05-19 00:03:1314709 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514710 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114711 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414712
Raul Tambre94493c652019-03-11 17:18:3514713 spdy::SpdySerializedFrame resp(
14714 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314715 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414716 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114717 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414718 };
14719
Ryan Sleevib8d7ea02018-05-07 20:01:0114720 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714721 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414722
[email protected]83039bb2011-12-09 18:43:5514723 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414724
danakj1fd259a02016-04-16 03:17:0914725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414726
bnc87dcefc2017-05-25 12:47:5814727 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914728 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414729
tfarina42834112016-09-22 13:38:2014730 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14732 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414733
14734 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214735 ASSERT_TRUE(response);
14736 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414737 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14738
14739 std::string response_data;
robpercival214763f2016-07-01 23:27:0114740 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414741 EXPECT_EQ("hello world", response_data);
14742
14743 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514744 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014745 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114746 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414747 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14748 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714749 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214750 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814751
bnc87dcefc2017-05-25 12:47:5814752 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914753 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414754
tfarina42834112016-09-22 13:38:2014755 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114756 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14757 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414758
14759 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214760 ASSERT_TRUE(response);
14761 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214762 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314763 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214764 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414765
robpercival214763f2016-07-01 23:27:0114766 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414767 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214768}
14769
[email protected]044de0642010-06-17 10:42:1514770// GenerateAuthToken is a mighty big test.
14771// It tests all permutation of GenerateAuthToken behavior:
14772// - Synchronous and Asynchronous completion.
14773// - OK or error on completion.
14774// - Direct connection, non-authenticating proxy, and authenticating proxy.
14775// - HTTP or HTTPS backend (to include proxy tunneling).
14776// - Non-authenticating and authenticating backend.
14777//
[email protected]fe3b7dc2012-02-03 19:52:0914778// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514779// problems generating an auth token for an authenticating proxy, we don't
14780// need to test all permutations of the backend server).
14781//
14782// The test proceeds by going over each of the configuration cases, and
14783// potentially running up to three rounds in each of the tests. The TestConfig
14784// specifies both the configuration for the test as well as the expectations
14785// for the results.
bncd16676a2016-07-20 16:23:0114786TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014787 static const char kServer[] = "http://www.example.com";
14788 static const char kSecureServer[] = "https://www.example.com";
14789 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514790
14791 enum AuthTiming {
14792 AUTH_NONE,
14793 AUTH_SYNC,
14794 AUTH_ASYNC,
14795 };
14796
14797 const MockWrite kGet(
14798 "GET / HTTP/1.1\r\n"
14799 "Host: www.example.com\r\n"
14800 "Connection: keep-alive\r\n\r\n");
14801 const MockWrite kGetProxy(
14802 "GET http://www.example.com/ HTTP/1.1\r\n"
14803 "Host: www.example.com\r\n"
14804 "Proxy-Connection: keep-alive\r\n\r\n");
14805 const MockWrite kGetAuth(
14806 "GET / HTTP/1.1\r\n"
14807 "Host: www.example.com\r\n"
14808 "Connection: keep-alive\r\n"
14809 "Authorization: auth_token\r\n\r\n");
14810 const MockWrite kGetProxyAuth(
14811 "GET http://www.example.com/ HTTP/1.1\r\n"
14812 "Host: www.example.com\r\n"
14813 "Proxy-Connection: keep-alive\r\n"
14814 "Proxy-Authorization: auth_token\r\n\r\n");
14815 const MockWrite kGetAuthThroughProxy(
14816 "GET http://www.example.com/ HTTP/1.1\r\n"
14817 "Host: www.example.com\r\n"
14818 "Proxy-Connection: keep-alive\r\n"
14819 "Authorization: auth_token\r\n\r\n");
14820 const MockWrite kGetAuthWithProxyAuth(
14821 "GET http://www.example.com/ HTTP/1.1\r\n"
14822 "Host: www.example.com\r\n"
14823 "Proxy-Connection: keep-alive\r\n"
14824 "Proxy-Authorization: auth_token\r\n"
14825 "Authorization: auth_token\r\n\r\n");
14826 const MockWrite kConnect(
14827 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714828 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514829 "Proxy-Connection: keep-alive\r\n\r\n");
14830 const MockWrite kConnectProxyAuth(
14831 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714832 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514833 "Proxy-Connection: keep-alive\r\n"
14834 "Proxy-Authorization: auth_token\r\n\r\n");
14835
14836 const MockRead kSuccess(
14837 "HTTP/1.1 200 OK\r\n"
14838 "Content-Type: text/html; charset=iso-8859-1\r\n"
14839 "Content-Length: 3\r\n\r\n"
14840 "Yes");
14841 const MockRead kFailure(
14842 "Should not be called.");
14843 const MockRead kServerChallenge(
14844 "HTTP/1.1 401 Unauthorized\r\n"
14845 "WWW-Authenticate: Mock realm=server\r\n"
14846 "Content-Type: text/html; charset=iso-8859-1\r\n"
14847 "Content-Length: 14\r\n\r\n"
14848 "Unauthorized\r\n");
14849 const MockRead kProxyChallenge(
14850 "HTTP/1.1 407 Unauthorized\r\n"
14851 "Proxy-Authenticate: Mock realm=proxy\r\n"
14852 "Proxy-Connection: close\r\n"
14853 "Content-Type: text/html; charset=iso-8859-1\r\n"
14854 "Content-Length: 14\r\n\r\n"
14855 "Unauthorized\r\n");
14856 const MockRead kProxyConnected(
14857 "HTTP/1.1 200 Connection Established\r\n\r\n");
14858
14859 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14860 // no constructors, but the C++ compiler on Windows warns about
14861 // unspecified data in compound literals. So, moved to using constructors,
14862 // and TestRound's created with the default constructor should not be used.
14863 struct TestRound {
14864 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514865 : expected_rv(ERR_UNEXPECTED),
14866 extra_write(nullptr),
14867 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314868 TestRound(const MockWrite& write_arg,
14869 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514870 int expected_rv_arg)
14871 : write(write_arg),
14872 read(read_arg),
14873 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514874 extra_write(nullptr),
14875 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514876 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14877 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114878 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514879 : write(write_arg),
14880 read(read_arg),
14881 expected_rv(expected_rv_arg),
14882 extra_write(extra_write_arg),
14883 extra_read(extra_read_arg) {
14884 }
14885 MockWrite write;
14886 MockRead read;
14887 int expected_rv;
14888 const MockWrite* extra_write;
14889 const MockRead* extra_read;
14890 };
14891
14892 static const int kNoSSL = 500;
14893
14894 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114895 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114896 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514897 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114898 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114899 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514900 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114901 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514902 int num_auth_rounds;
14903 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614904 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514905 } test_configs[] = {
asankac93076192016-10-03 15:46:0214906 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114907 {__LINE__,
14908 nullptr,
asankac93076192016-10-03 15:46:0214909 AUTH_NONE,
14910 OK,
14911 kServer,
14912 AUTH_NONE,
14913 OK,
14914 1,
14915 kNoSSL,
14916 {TestRound(kGet, kSuccess, OK)}},
14917 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114918 {__LINE__,
14919 nullptr,
asankac93076192016-10-03 15:46:0214920 AUTH_NONE,
14921 OK,
14922 kServer,
14923 AUTH_SYNC,
14924 OK,
14925 2,
14926 kNoSSL,
14927 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514928 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114929 {__LINE__,
14930 nullptr,
asankac93076192016-10-03 15:46:0214931 AUTH_NONE,
14932 OK,
14933 kServer,
14934 AUTH_SYNC,
14935 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614936 3,
14937 kNoSSL,
14938 {TestRound(kGet, kServerChallenge, OK),
14939 TestRound(kGet, kServerChallenge, OK),
14940 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114941 {__LINE__,
14942 nullptr,
asankae2257db2016-10-11 22:03:1614943 AUTH_NONE,
14944 OK,
14945 kServer,
14946 AUTH_SYNC,
14947 ERR_UNSUPPORTED_AUTH_SCHEME,
14948 2,
14949 kNoSSL,
14950 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114951 {__LINE__,
14952 nullptr,
asankae2257db2016-10-11 22:03:1614953 AUTH_NONE,
14954 OK,
14955 kServer,
14956 AUTH_SYNC,
14957 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14958 2,
14959 kNoSSL,
14960 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114961 {__LINE__,
14962 kProxy,
asankae2257db2016-10-11 22:03:1614963 AUTH_SYNC,
14964 ERR_FAILED,
14965 kServer,
14966 AUTH_NONE,
14967 OK,
14968 2,
14969 kNoSSL,
14970 {TestRound(kGetProxy, kProxyChallenge, OK),
14971 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114972 {__LINE__,
14973 kProxy,
asankae2257db2016-10-11 22:03:1614974 AUTH_ASYNC,
14975 ERR_FAILED,
14976 kServer,
14977 AUTH_NONE,
14978 OK,
14979 2,
14980 kNoSSL,
14981 {TestRound(kGetProxy, kProxyChallenge, OK),
14982 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114983 {__LINE__,
14984 nullptr,
asankae2257db2016-10-11 22:03:1614985 AUTH_NONE,
14986 OK,
14987 kServer,
14988 AUTH_SYNC,
14989 ERR_FAILED,
asankac93076192016-10-03 15:46:0214990 2,
14991 kNoSSL,
14992 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614993 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114994 {__LINE__,
14995 nullptr,
asankae2257db2016-10-11 22:03:1614996 AUTH_NONE,
14997 OK,
14998 kServer,
14999 AUTH_ASYNC,
15000 ERR_FAILED,
15001 2,
15002 kNoSSL,
15003 {TestRound(kGet, kServerChallenge, OK),
15004 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115005 {__LINE__,
15006 nullptr,
asankac93076192016-10-03 15:46:0215007 AUTH_NONE,
15008 OK,
15009 kServer,
15010 AUTH_ASYNC,
15011 OK,
15012 2,
15013 kNoSSL,
15014 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515015 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115016 {__LINE__,
15017 nullptr,
asankac93076192016-10-03 15:46:0215018 AUTH_NONE,
15019 OK,
15020 kServer,
15021 AUTH_ASYNC,
15022 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615023 3,
asankac93076192016-10-03 15:46:0215024 kNoSSL,
15025 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615026 // The second round uses a HttpAuthHandlerMock that always succeeds.
15027 TestRound(kGet, kServerChallenge, OK),
15028 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215029 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115030 {__LINE__,
15031 kProxy,
asankac93076192016-10-03 15:46:0215032 AUTH_NONE,
15033 OK,
15034 kServer,
15035 AUTH_NONE,
15036 OK,
15037 1,
15038 kNoSSL,
15039 {TestRound(kGetProxy, kSuccess, OK)}},
15040 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115041 {__LINE__,
15042 kProxy,
asankac93076192016-10-03 15:46:0215043 AUTH_NONE,
15044 OK,
15045 kServer,
15046 AUTH_SYNC,
15047 OK,
15048 2,
15049 kNoSSL,
15050 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515051 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115052 {__LINE__,
15053 kProxy,
asankac93076192016-10-03 15:46:0215054 AUTH_NONE,
15055 OK,
15056 kServer,
15057 AUTH_SYNC,
15058 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615059 3,
asankac93076192016-10-03 15:46:0215060 kNoSSL,
15061 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615062 TestRound(kGetProxy, kServerChallenge, OK),
15063 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115064 {__LINE__,
15065 kProxy,
asankac93076192016-10-03 15:46:0215066 AUTH_NONE,
15067 OK,
15068 kServer,
15069 AUTH_ASYNC,
15070 OK,
15071 2,
15072 kNoSSL,
15073 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515074 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115075 {__LINE__,
15076 kProxy,
asankac93076192016-10-03 15:46:0215077 AUTH_NONE,
15078 OK,
15079 kServer,
15080 AUTH_ASYNC,
15081 ERR_INVALID_AUTH_CREDENTIALS,
15082 2,
15083 kNoSSL,
15084 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615085 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215086 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115087 {__LINE__,
15088 kProxy,
asankac93076192016-10-03 15:46:0215089 AUTH_SYNC,
15090 OK,
15091 kServer,
15092 AUTH_NONE,
15093 OK,
15094 2,
15095 kNoSSL,
15096 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515097 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115098 {__LINE__,
15099 kProxy,
asankac93076192016-10-03 15:46:0215100 AUTH_SYNC,
15101 ERR_INVALID_AUTH_CREDENTIALS,
15102 kServer,
15103 AUTH_NONE,
15104 OK,
15105 2,
15106 kNoSSL,
15107 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615108 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115109 {__LINE__,
15110 kProxy,
asankac93076192016-10-03 15:46:0215111 AUTH_ASYNC,
15112 OK,
15113 kServer,
15114 AUTH_NONE,
15115 OK,
15116 2,
15117 kNoSSL,
15118 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515119 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115120 {__LINE__,
15121 kProxy,
asankac93076192016-10-03 15:46:0215122 AUTH_ASYNC,
15123 ERR_INVALID_AUTH_CREDENTIALS,
15124 kServer,
15125 AUTH_NONE,
15126 OK,
15127 2,
15128 kNoSSL,
15129 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615130 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115131 {__LINE__,
15132 kProxy,
15133 AUTH_ASYNC,
15134 ERR_INVALID_AUTH_CREDENTIALS,
15135 kServer,
15136 AUTH_NONE,
15137 OK,
15138 3,
15139 kNoSSL,
15140 {TestRound(kGetProxy, kProxyChallenge, OK),
15141 TestRound(kGetProxy, kProxyChallenge, OK),
15142 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215143 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115144 {__LINE__,
15145 kProxy,
asankac93076192016-10-03 15:46:0215146 AUTH_SYNC,
15147 OK,
15148 kServer,
15149 AUTH_SYNC,
15150 OK,
15151 3,
15152 kNoSSL,
15153 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515154 TestRound(kGetProxyAuth, kServerChallenge, OK),
15155 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115156 {__LINE__,
15157 kProxy,
asankac93076192016-10-03 15:46:0215158 AUTH_SYNC,
15159 OK,
15160 kServer,
15161 AUTH_SYNC,
15162 ERR_INVALID_AUTH_CREDENTIALS,
15163 3,
15164 kNoSSL,
15165 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515166 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615167 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115168 {__LINE__,
15169 kProxy,
asankac93076192016-10-03 15:46:0215170 AUTH_ASYNC,
15171 OK,
15172 kServer,
15173 AUTH_SYNC,
15174 OK,
15175 3,
15176 kNoSSL,
15177 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515178 TestRound(kGetProxyAuth, kServerChallenge, OK),
15179 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115180 {__LINE__,
15181 kProxy,
asankac93076192016-10-03 15:46:0215182 AUTH_ASYNC,
15183 OK,
15184 kServer,
15185 AUTH_SYNC,
15186 ERR_INVALID_AUTH_CREDENTIALS,
15187 3,
15188 kNoSSL,
15189 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515190 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615191 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115192 {__LINE__,
15193 kProxy,
asankac93076192016-10-03 15:46:0215194 AUTH_SYNC,
15195 OK,
15196 kServer,
15197 AUTH_ASYNC,
15198 OK,
15199 3,
15200 kNoSSL,
15201 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515202 TestRound(kGetProxyAuth, kServerChallenge, OK),
15203 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115204 {__LINE__,
15205 kProxy,
15206 AUTH_SYNC,
15207 ERR_INVALID_AUTH_CREDENTIALS,
15208 kServer,
15209 AUTH_ASYNC,
15210 OK,
15211 4,
15212 kNoSSL,
15213 {TestRound(kGetProxy, kProxyChallenge, OK),
15214 TestRound(kGetProxy, kProxyChallenge, OK),
15215 TestRound(kGetProxyAuth, kServerChallenge, OK),
15216 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
15217 {__LINE__,
15218 kProxy,
asankac93076192016-10-03 15:46:0215219 AUTH_SYNC,
15220 OK,
15221 kServer,
15222 AUTH_ASYNC,
15223 ERR_INVALID_AUTH_CREDENTIALS,
15224 3,
15225 kNoSSL,
15226 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515227 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615228 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115229 {__LINE__,
15230 kProxy,
asankac93076192016-10-03 15:46:0215231 AUTH_ASYNC,
15232 OK,
15233 kServer,
15234 AUTH_ASYNC,
15235 OK,
15236 3,
15237 kNoSSL,
15238 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515239 TestRound(kGetProxyAuth, kServerChallenge, OK),
15240 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115241 {__LINE__,
15242 kProxy,
asankac93076192016-10-03 15:46:0215243 AUTH_ASYNC,
15244 OK,
15245 kServer,
15246 AUTH_ASYNC,
15247 ERR_INVALID_AUTH_CREDENTIALS,
15248 3,
15249 kNoSSL,
15250 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515251 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615252 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115253 {__LINE__,
15254 kProxy,
15255 AUTH_ASYNC,
15256 ERR_INVALID_AUTH_CREDENTIALS,
15257 kServer,
15258 AUTH_ASYNC,
15259 ERR_INVALID_AUTH_CREDENTIALS,
15260 4,
15261 kNoSSL,
15262 {TestRound(kGetProxy, kProxyChallenge, OK),
15263 TestRound(kGetProxy, kProxyChallenge, OK),
15264 TestRound(kGetProxyAuth, kServerChallenge, OK),
15265 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215266 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115267 {__LINE__,
15268 nullptr,
asankac93076192016-10-03 15:46:0215269 AUTH_NONE,
15270 OK,
15271 kSecureServer,
15272 AUTH_NONE,
15273 OK,
15274 1,
15275 0,
15276 {TestRound(kGet, kSuccess, OK)}},
15277 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115278 {__LINE__,
15279 nullptr,
asankac93076192016-10-03 15:46:0215280 AUTH_NONE,
15281 OK,
15282 kSecureServer,
15283 AUTH_SYNC,
15284 OK,
15285 2,
15286 0,
15287 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515288 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115289 {__LINE__,
15290 nullptr,
asankac93076192016-10-03 15:46:0215291 AUTH_NONE,
15292 OK,
15293 kSecureServer,
15294 AUTH_SYNC,
15295 ERR_INVALID_AUTH_CREDENTIALS,
15296 2,
15297 0,
asankae2257db2016-10-11 22:03:1615298 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115299 {__LINE__,
15300 nullptr,
asankac93076192016-10-03 15:46:0215301 AUTH_NONE,
15302 OK,
15303 kSecureServer,
15304 AUTH_ASYNC,
15305 OK,
15306 2,
15307 0,
15308 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515309 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115310 {__LINE__,
15311 nullptr,
asankac93076192016-10-03 15:46:0215312 AUTH_NONE,
15313 OK,
15314 kSecureServer,
15315 AUTH_ASYNC,
15316 ERR_INVALID_AUTH_CREDENTIALS,
15317 2,
15318 0,
asankae2257db2016-10-11 22:03:1615319 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215320 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115321 {__LINE__,
15322 kProxy,
asankac93076192016-10-03 15:46:0215323 AUTH_NONE,
15324 OK,
15325 kSecureServer,
15326 AUTH_NONE,
15327 OK,
15328 1,
15329 0,
15330 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
15331 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115332 {__LINE__,
15333 kProxy,
asankac93076192016-10-03 15:46:0215334 AUTH_NONE,
15335 OK,
15336 kSecureServer,
15337 AUTH_SYNC,
15338 OK,
15339 2,
15340 0,
15341 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515342 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115343 {__LINE__,
15344 kProxy,
asankac93076192016-10-03 15:46:0215345 AUTH_NONE,
15346 OK,
15347 kSecureServer,
15348 AUTH_SYNC,
15349 ERR_INVALID_AUTH_CREDENTIALS,
15350 2,
15351 0,
15352 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615353 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115354 {__LINE__,
15355 kProxy,
asankac93076192016-10-03 15:46:0215356 AUTH_NONE,
15357 OK,
15358 kSecureServer,
15359 AUTH_ASYNC,
15360 OK,
15361 2,
15362 0,
15363 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515364 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115365 {__LINE__,
15366 kProxy,
asankac93076192016-10-03 15:46:0215367 AUTH_NONE,
15368 OK,
15369 kSecureServer,
15370 AUTH_ASYNC,
15371 ERR_INVALID_AUTH_CREDENTIALS,
15372 2,
15373 0,
15374 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615375 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215376 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115377 {__LINE__,
15378 kProxy,
asankac93076192016-10-03 15:46:0215379 AUTH_SYNC,
15380 OK,
15381 kSecureServer,
15382 AUTH_NONE,
15383 OK,
15384 2,
15385 1,
15386 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515387 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115388 {__LINE__,
15389 kProxy,
asankac93076192016-10-03 15:46:0215390 AUTH_SYNC,
15391 ERR_INVALID_AUTH_CREDENTIALS,
15392 kSecureServer,
15393 AUTH_NONE,
15394 OK,
15395 2,
15396 kNoSSL,
15397 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615398 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115399 {__LINE__,
15400 kProxy,
asankae2257db2016-10-11 22:03:1615401 AUTH_SYNC,
15402 ERR_UNSUPPORTED_AUTH_SCHEME,
15403 kSecureServer,
15404 AUTH_NONE,
15405 OK,
15406 2,
15407 kNoSSL,
15408 {TestRound(kConnect, kProxyChallenge, OK),
15409 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115410 {__LINE__,
15411 kProxy,
asankae2257db2016-10-11 22:03:1615412 AUTH_SYNC,
15413 ERR_UNEXPECTED,
15414 kSecureServer,
15415 AUTH_NONE,
15416 OK,
15417 2,
15418 kNoSSL,
15419 {TestRound(kConnect, kProxyChallenge, OK),
15420 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115421 {__LINE__,
15422 kProxy,
asankac93076192016-10-03 15:46:0215423 AUTH_ASYNC,
15424 OK,
15425 kSecureServer,
15426 AUTH_NONE,
15427 OK,
15428 2,
15429 1,
15430 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515431 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115432 {__LINE__,
15433 kProxy,
asankac93076192016-10-03 15:46:0215434 AUTH_ASYNC,
15435 ERR_INVALID_AUTH_CREDENTIALS,
15436 kSecureServer,
15437 AUTH_NONE,
15438 OK,
15439 2,
15440 kNoSSL,
15441 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615442 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215443 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115444 {__LINE__,
15445 kProxy,
asankac93076192016-10-03 15:46:0215446 AUTH_SYNC,
15447 OK,
15448 kSecureServer,
15449 AUTH_SYNC,
15450 OK,
15451 3,
15452 1,
15453 {TestRound(kConnect, kProxyChallenge, OK),
15454 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15455 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515456 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115457 {__LINE__,
15458 kProxy,
asankac93076192016-10-03 15:46:0215459 AUTH_SYNC,
15460 OK,
15461 kSecureServer,
15462 AUTH_SYNC,
15463 ERR_INVALID_AUTH_CREDENTIALS,
15464 3,
15465 1,
15466 {TestRound(kConnect, kProxyChallenge, OK),
15467 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15468 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615469 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115470 {__LINE__,
15471 kProxy,
asankac93076192016-10-03 15:46:0215472 AUTH_ASYNC,
15473 OK,
15474 kSecureServer,
15475 AUTH_SYNC,
15476 OK,
15477 3,
15478 1,
15479 {TestRound(kConnect, kProxyChallenge, OK),
15480 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15481 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515482 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115483 {__LINE__,
15484 kProxy,
asankac93076192016-10-03 15:46:0215485 AUTH_ASYNC,
15486 OK,
15487 kSecureServer,
15488 AUTH_SYNC,
15489 ERR_INVALID_AUTH_CREDENTIALS,
15490 3,
15491 1,
15492 {TestRound(kConnect, kProxyChallenge, OK),
15493 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15494 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615495 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115496 {__LINE__,
15497 kProxy,
asankac93076192016-10-03 15:46:0215498 AUTH_SYNC,
15499 OK,
15500 kSecureServer,
15501 AUTH_ASYNC,
15502 OK,
15503 3,
15504 1,
15505 {TestRound(kConnect, kProxyChallenge, OK),
15506 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15507 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515508 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115509 {__LINE__,
15510 kProxy,
asankac93076192016-10-03 15:46:0215511 AUTH_SYNC,
15512 OK,
15513 kSecureServer,
15514 AUTH_ASYNC,
15515 ERR_INVALID_AUTH_CREDENTIALS,
15516 3,
15517 1,
15518 {TestRound(kConnect, kProxyChallenge, OK),
15519 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15520 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615521 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115522 {__LINE__,
15523 kProxy,
asankac93076192016-10-03 15:46:0215524 AUTH_ASYNC,
15525 OK,
15526 kSecureServer,
15527 AUTH_ASYNC,
15528 OK,
15529 3,
15530 1,
15531 {TestRound(kConnect, kProxyChallenge, OK),
15532 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15533 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515534 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115535 {__LINE__,
15536 kProxy,
asankac93076192016-10-03 15:46:0215537 AUTH_ASYNC,
15538 OK,
15539 kSecureServer,
15540 AUTH_ASYNC,
15541 ERR_INVALID_AUTH_CREDENTIALS,
15542 3,
15543 1,
15544 {TestRound(kConnect, kProxyChallenge, OK),
15545 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15546 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615547 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115548 {__LINE__,
15549 kProxy,
15550 AUTH_ASYNC,
15551 ERR_INVALID_AUTH_CREDENTIALS,
15552 kSecureServer,
15553 AUTH_ASYNC,
15554 ERR_INVALID_AUTH_CREDENTIALS,
15555 4,
15556 2,
15557 {TestRound(kConnect, kProxyChallenge, OK),
15558 TestRound(kConnect, kProxyChallenge, OK),
15559 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15560 &kServerChallenge),
15561 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515562 };
15563
asanka463ca4262016-11-16 02:34:3115564 for (const auto& test_config : test_configs) {
15565 SCOPED_TRACE(::testing::Message() << "Test config at "
15566 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815567 HttpAuthHandlerMock::Factory* auth_factory(
15568 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715569 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915570 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615571
15572 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515573 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115574 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815575 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15576 std::string auth_challenge = "Mock realm=proxy";
15577 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415578 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15579 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815580 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
Matt Menke618134b2020-05-22 02:12:2715581 empty_ssl_info, NetworkIsolationKey(),
15582 origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815583 auth_handler->SetGenerateExpectation(
15584 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115585 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815586 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15587 }
[email protected]044de0642010-06-17 10:42:1515588 }
15589 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015590 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515591 std::string auth_challenge = "Mock realm=server";
15592 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415593 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15594 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515595 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715596 empty_ssl_info, NetworkIsolationKey(),
15597 origin, NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515598 auth_handler->SetGenerateExpectation(
15599 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115600 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815601 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615602
15603 // The second handler always succeeds. It should only be used where there
15604 // are multiple auth sessions for server auth in the same network
15605 // transaction using the same auth scheme.
15606 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915607 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615608 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715609 empty_ssl_info, NetworkIsolationKey(),
15610 origin, NetLogWithSource());
asankae2257db2016-10-11 22:03:1615611 second_handler->SetGenerateExpectation(true, OK);
15612 auth_factory->AddMockHandler(second_handler.release(),
15613 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515614 }
15615 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915616 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615617 ConfiguredProxyResolutionService::CreateFixed(
15618 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515619 } else {
Bence Béky53a5aef2018-03-29 21:54:1215620 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615621 ConfiguredProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515622 }
15623
15624 HttpRequestInfo request;
15625 request.method = "GET";
15626 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1015627 request.traffic_annotation =
15628 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515629
danakj1fd259a02016-04-16 03:17:0915630 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515631
rchcb68dc62015-05-21 04:45:3615632 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15633
15634 std::vector<std::vector<MockRead>> mock_reads(1);
15635 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515636 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215637 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515638 const TestRound& read_write_round = test_config.rounds[round];
15639
15640 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615641 mock_reads.back().push_back(read_write_round.read);
15642 mock_writes.back().push_back(read_write_round.write);
15643
15644 // kProxyChallenge uses Proxy-Connection: close which means that the
15645 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415646 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615647 mock_reads.push_back(std::vector<MockRead>());
15648 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515649 }
15650
rchcb68dc62015-05-21 04:45:3615651 if (read_write_round.extra_read) {
15652 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515653 }
rchcb68dc62015-05-21 04:45:3615654 if (read_write_round.extra_write) {
15655 mock_writes.back().push_back(*read_write_round.extra_write);
15656 }
[email protected]044de0642010-06-17 10:42:1515657
15658 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515659 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715660 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515661 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615662 }
[email protected]044de0642010-06-17 10:42:1515663
danakj1fd259a02016-04-16 03:17:0915664 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615665 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915666 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115667 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615668 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215669 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615670 }
15671
mmenkecc2298e2015-12-07 18:20:1815672 // Transaction must be created after DataProviders, so it's destroyed before
15673 // they are as well.
15674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15675
rchcb68dc62015-05-21 04:45:3615676 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215677 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615678 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515679 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115680 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515681 int rv;
15682 if (round == 0) {
tfarina42834112016-09-22 13:38:2015683 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515684 } else {
[email protected]49639fa2011-12-20 23:22:4115685 rv = trans.RestartWithAuth(
15686 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515687 }
15688 if (rv == ERR_IO_PENDING)
15689 rv = callback.WaitForResult();
15690
15691 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615692 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015693 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515694 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515695 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15696 continue;
15697 }
15698 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815699 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515700 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815701 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615702 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515703 }
15704 }
[email protected]e5ae96a2010-04-14 20:12:4515705 }
15706}
15707
bncd16676a2016-07-20 16:23:0115708TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415709 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415710 HttpAuthHandlerMock::Factory* auth_factory(
15711 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715712 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215713 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615714 ConfiguredProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715715 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415716
15717 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15718 auth_handler->set_connection_based(true);
15719 std::string auth_challenge = "Mock realm=server";
15720 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415721 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15722 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915723 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415724 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715725 empty_ssl_info, NetworkIsolationKey(), origin,
15726 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815727 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415728
[email protected]c871bce92010-07-15 21:51:1415729 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515730 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415731 HttpRequestInfo request;
15732 request.method = "GET";
15733 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1015734 request.traffic_annotation =
15735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715736
danakj1fd259a02016-04-16 03:17:0915737 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015738
15739 // Use a TCP Socket Pool with only one connection per group. This is used
15740 // to validate that the TCP socket is not released to the pool between
15741 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215742 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615743 CommonConnectJobParams common_connect_job_params(
15744 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815745 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915746 50, // Max sockets for pool
15747 1, // Max sockets per group
15748 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615749 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215750 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915751 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015752 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15753 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815754 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015755
bnc691fda62016-08-12 00:43:1615756 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115757 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415758
15759 const MockWrite kGet(
15760 "GET / HTTP/1.1\r\n"
15761 "Host: www.example.com\r\n"
15762 "Connection: keep-alive\r\n\r\n");
15763 const MockWrite kGetAuth(
15764 "GET / HTTP/1.1\r\n"
15765 "Host: www.example.com\r\n"
15766 "Connection: keep-alive\r\n"
15767 "Authorization: auth_token\r\n\r\n");
15768
15769 const MockRead kServerChallenge(
15770 "HTTP/1.1 401 Unauthorized\r\n"
15771 "WWW-Authenticate: Mock realm=server\r\n"
15772 "Content-Type: text/html; charset=iso-8859-1\r\n"
15773 "Content-Length: 14\r\n\r\n"
15774 "Unauthorized\r\n");
15775 const MockRead kSuccess(
15776 "HTTP/1.1 200 OK\r\n"
15777 "Content-Type: text/html; charset=iso-8859-1\r\n"
15778 "Content-Length: 3\r\n\r\n"
15779 "Yes");
15780
15781 MockWrite writes[] = {
15782 // First round
15783 kGet,
15784 // Second round
15785 kGetAuth,
15786 // Third round
15787 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015788 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015789 kGetAuth,
15790 // Competing request
15791 kGet,
[email protected]c871bce92010-07-15 21:51:1415792 };
15793 MockRead reads[] = {
15794 // First round
15795 kServerChallenge,
15796 // Second round
15797 kServerChallenge,
15798 // Third round
[email protected]eca50e122010-09-11 14:03:3015799 kServerChallenge,
15800 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415801 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015802 // Competing response
15803 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415804 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115805 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715806 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415807
Matt Menkef6edce752019-03-19 17:21:5615808 const ClientSocketPool::GroupId kSocketGroup(
15809 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415810 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15811 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015812
15813 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415814 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015815 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415816 if (rv == ERR_IO_PENDING)
15817 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115818 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615819 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215820 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815821 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315822 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115823 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15824 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415825
[email protected]7ef4cbbb2011-02-06 11:19:1015826 // In between rounds, another request comes in for the same domain.
15827 // It should not be able to grab the TCP socket that trans has already
15828 // claimed.
bnc691fda62016-08-12 00:43:1615829 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115830 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015831 rv = trans_compete.Start(&request, callback_compete.callback(),
15832 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115833 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015834 // callback_compete.WaitForResult at this point would stall forever,
15835 // since the HttpNetworkTransaction does not release the request back to
15836 // the pool until after authentication completes.
15837
15838 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415839 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615840 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415841 if (rv == ERR_IO_PENDING)
15842 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115843 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615844 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215845 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815846 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315847 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115848 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15849 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415850
[email protected]7ef4cbbb2011-02-06 11:19:1015851 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415852 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615853 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415854 if (rv == ERR_IO_PENDING)
15855 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115856 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615857 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215858 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815859 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315860 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115861 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15862 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015863
[email protected]7ef4cbbb2011-02-06 11:19:1015864 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015865 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615866 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015867 if (rv == ERR_IO_PENDING)
15868 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115869 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615870 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215871 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815872 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315873 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015874
asanka463ca4262016-11-16 02:34:3115875 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15876 // auth handler should transition to a DONE state in concert with the remote
15877 // server. But that's not something we can test here with a mock handler.
15878 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15879 auth_handler->state());
15880
[email protected]7ef4cbbb2011-02-06 11:19:1015881 // Read the body since the fourth round was successful. This will also
15882 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415883 scoped_refptr<IOBufferWithSize> io_buf =
15884 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615885 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015886 if (rv == ERR_IO_PENDING)
15887 rv = callback.WaitForResult();
15888 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615889 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015890 EXPECT_EQ(0, rv);
15891 // There are still 0 idle sockets, since the trans_compete transaction
15892 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315893 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015894
15895 // The competing request can now finish. Wait for the headers and then
15896 // read the body.
15897 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115898 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615899 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015900 if (rv == ERR_IO_PENDING)
15901 rv = callback.WaitForResult();
15902 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615903 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015904 EXPECT_EQ(0, rv);
15905
15906 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315907 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415908}
15909
[email protected]65041fa2010-05-21 06:56:5315910// This tests the case that a request is issued via http instead of spdy after
15911// npn is negotiated.
bncd16676a2016-07-20 16:23:0115912TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315913 HttpRequestInfo request;
15914 request.method = "GET";
bncce36dca22015-04-21 22:11:2315915 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015916 request.traffic_annotation =
15917 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315918
15919 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315920 MockWrite(
15921 "GET / HTTP/1.1\r\n"
15922 "Host: www.example.org\r\n"
15923 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315924 };
15925
15926 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215927 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315928 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215929 MockRead("\r\n"),
15930 MockRead("hello world"),
15931 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315932 };
15933
[email protected]8ddf8322012-02-23 18:08:0615934 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615935 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315936
[email protected]bb88e1d32013-05-03 23:11:0715937 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315938
Ryan Sleevib8d7ea02018-05-07 20:01:0115939 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715940 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315941
[email protected]49639fa2011-12-20 23:22:4115942 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315943
danakj1fd259a02016-04-16 03:17:0915944 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315946
tfarina42834112016-09-22 13:38:2015947 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315948
robpercival214763f2016-07-01 23:27:0115949 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15950 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315951
bnc691fda62016-08-12 00:43:1615952 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215953 ASSERT_TRUE(response);
15954 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315955 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15956
15957 std::string response_data;
bnc691fda62016-08-12 00:43:1615958 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315959 EXPECT_EQ("hello world", response_data);
15960
15961 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215962 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315963}
[email protected]26ef6582010-06-24 02:30:4715964
bnc55ff9da2015-08-19 18:42:3515965// Simulate the SSL handshake completing with an NPN negotiation followed by an
15966// immediate server closing of the socket.
15967// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115968TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715969 HttpRequestInfo request;
15970 request.method = "GET";
bncce36dca22015-04-21 22:11:2315971 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015972 request.traffic_annotation =
15973 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715974
[email protected]8ddf8322012-02-23 18:08:0615975 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615976 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715977 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715978
Ryan Hamilton0239aac2018-05-19 00:03:1315979 spdy::SpdySerializedFrame req(
15980 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115981 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715982
15983 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615984 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715985 };
15986
Ryan Sleevib8d7ea02018-05-07 20:01:0115987 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715988 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715989
[email protected]49639fa2011-12-20 23:22:4115990 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715991
danakj1fd259a02016-04-16 03:17:0915992 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615993 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715994
tfarina42834112016-09-22 13:38:2015995 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115996 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15997 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715998}
[email protected]65d34382010-07-01 18:12:2615999
[email protected]795cbf82013-07-22 09:37:2716000// A subclass of HttpAuthHandlerMock that records the request URL when
16001// it gets it. This is needed since the auth handler may get destroyed
16002// before we get a chance to query it.
16003class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
16004 public:
16005 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
16006
Chris Watkins7a41d3552017-12-01 02:13:2716007 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2716008
16009 protected:
dchengb03027d2014-10-21 12:00:2016010 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
16011 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0916012 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2016013 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2716014 *url_ = request->url;
16015 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0916016 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2716017 }
16018
16019 private:
16020 GURL* url_;
16021};
16022
[email protected]8e6441ca2010-08-19 05:56:3816023// Test that if we cancel the transaction as the connection is completing, that
16024// everything tears down correctly.
bncd16676a2016-07-20 16:23:0116025TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3816026 // Setup everything about the connection to complete synchronously, so that
16027 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
16028 // for is the callback from the HttpStreamRequest.
16029 // Then cancel the transaction.
16030 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3616031 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3816032 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0616033 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
16034 MockRead(SYNCHRONOUS, "hello world"),
16035 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3816036 };
16037
[email protected]8e6441ca2010-08-19 05:56:3816038 HttpRequestInfo request;
16039 request.method = "GET";
bncce36dca22015-04-21 22:11:2316040 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016041 request.traffic_annotation =
16042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3816043
danakj1fd259a02016-04-16 03:17:0916044 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5816045 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916046 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2716047
Ryan Sleevib8d7ea02018-05-07 20:01:0116048 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3816049 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0716050 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3816051
[email protected]49639fa2011-12-20 23:22:4116052 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3816053
Matt Muellerd9342e3a2019-11-26 01:41:1416054 RecordingBoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4116055 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116056 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3816057 trans.reset(); // Cancel the transaction here.
16058
fdoray92e35a72016-06-10 15:54:5516059 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3016060}
16061
[email protected]ecab6e052014-05-16 14:58:1216062// Test that if a transaction is cancelled after receiving the headers, the
16063// stream is drained properly and added back to the socket pool. The main
16064// purpose of this test is to make sure that an HttpStreamParser can be read
16065// from after the HttpNetworkTransaction and the objects it owns have been
16066// deleted.
16067// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0116068TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1216069 MockRead data_reads[] = {
16070 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
16071 MockRead(ASYNC, "Content-Length: 2\r\n"),
16072 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
16073 MockRead(ASYNC, "1"),
16074 // 2 async reads are necessary to trigger a ReadResponseBody call after the
16075 // HttpNetworkTransaction has been deleted.
16076 MockRead(ASYNC, "2"),
16077 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
16078 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116079 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1216080 session_deps_.socket_factory->AddSocketDataProvider(&data);
16081
danakj1fd259a02016-04-16 03:17:0916082 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1216083
16084 {
16085 HttpRequestInfo request;
16086 request.method = "GET";
bncce36dca22015-04-21 22:11:2316087 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016088 request.traffic_annotation =
16089 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1216090
dcheng48459ac22014-08-26 00:46:4116091 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1216092 TestCompletionCallback callback;
16093
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));
[email protected]ecab6e052014-05-16 14:58:1216096 callback.WaitForResult();
16097
16098 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216099 ASSERT_TRUE(response);
16100 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1216101 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16102
16103 // The transaction and HttpRequestInfo are deleted.
16104 }
16105
16106 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5516107 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1216108
16109 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4116110 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1216111}
16112
[email protected]76a505b2010-08-25 06:23:0016113// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0116114TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916115 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616116 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916117 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416118 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716119 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916120 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016121
[email protected]76a505b2010-08-25 06:23:0016122 HttpRequestInfo request;
16123 request.method = "GET";
bncce36dca22015-04-21 22:11:2316124 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016125 request.traffic_annotation =
16126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016127
16128 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2316129 MockWrite(
16130 "GET http://www.example.org/ HTTP/1.1\r\n"
16131 "Host: www.example.org\r\n"
16132 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016133 };
16134
16135 MockRead data_reads1[] = {
16136 MockRead("HTTP/1.1 200 OK\r\n"),
16137 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16138 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616139 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016140 };
16141
Ryan Sleevib8d7ea02018-05-07 20:01:0116142 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716143 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0016144
[email protected]49639fa2011-12-20 23:22:4116145 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016146
bnc691fda62016-08-12 00:43:1616147 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216148 ConnectedHandler connected_handler;
16149 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016150
bnc691fda62016-08-12 00:43:1616151 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116152 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016153
16154 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116155 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0016156
bnc691fda62016-08-12 00:43:1616157 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216158 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016159
16160 EXPECT_TRUE(response->headers->IsKeepAlive());
16161 EXPECT_EQ(200, response->headers->response_code());
16162 EXPECT_EQ(100, response->headers->GetContentLength());
16163 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716164 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16165 HostPortPair::FromString("myproxy:70")),
16166 response->proxy_server);
[email protected]76a505b2010-08-25 06:23:0016167 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2016168
Titouan Rigoudyba507a882020-07-31 12:15:1516169 TransportInfo expected_transport;
16170 expected_transport.type = TransportType::kProxied;
16171 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16172 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
16173
[email protected]029c83b62013-01-24 05:28:2016174 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616175 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016176 TestLoadTimingNotReusedWithPac(load_timing_info,
16177 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0016178}
16179
16180// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0116181TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916182 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616183 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916184 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416185 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716186 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916187 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016188
[email protected]76a505b2010-08-25 06:23:0016189 HttpRequestInfo request;
16190 request.method = "GET";
bncce36dca22015-04-21 22:11:2316191 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016192 request.traffic_annotation =
16193 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016194
16195 // Since we have proxy, should try to establish tunnel.
16196 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716197 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16198 "Host: www.example.org:443\r\n"
16199 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016200
rsleevidb16bb02015-11-12 23:47:1716201 MockWrite("GET / HTTP/1.1\r\n"
16202 "Host: www.example.org\r\n"
16203 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016204 };
16205
16206 MockRead data_reads1[] = {
16207 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16208
16209 MockRead("HTTP/1.1 200 OK\r\n"),
16210 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16211 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616212 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016213 };
16214
Ryan Sleevib8d7ea02018-05-07 20:01:0116215 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716216 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616217 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716218 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016219
[email protected]49639fa2011-12-20 23:22:4116220 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016221
bnc691fda62016-08-12 00:43:1616222 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216223 ConnectedHandler connected_handler;
16224 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016225
bnc691fda62016-08-12 00:43:1616226 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116227 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016228
16229 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116230 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416231 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016232 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016233 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16234 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016235 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016236 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016237 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16238 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016239
bnc691fda62016-08-12 00:43:1616240 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216241 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016242
16243 EXPECT_TRUE(response->headers->IsKeepAlive());
16244 EXPECT_EQ(200, response->headers->response_code());
16245 EXPECT_EQ(100, response->headers->GetContentLength());
16246 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16247 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716248 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16249 HostPortPair::FromString("myproxy:70")),
16250 response->proxy_server);
Titouan Rigoudyba507a882020-07-31 12:15:1516251
16252 TransportInfo expected_transport;
16253 expected_transport.type = TransportType::kProxied;
16254 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16255 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
[email protected]029c83b62013-01-24 05:28:2016256
16257 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616258 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016259 TestLoadTimingNotReusedWithPac(load_timing_info,
16260 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0016261}
16262
rsleevidb16bb02015-11-12 23:47:1716263// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
16264// literal host.
bncd16676a2016-07-20 16:23:0116265TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5916266 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616267 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916268 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416269 RecordingBoundTestNetLog log;
rsleevidb16bb02015-11-12 23:47:1716270 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1716272
16273 HttpRequestInfo request;
16274 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1516275 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1016276 request.traffic_annotation =
16277 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1716278
16279 // Since we have proxy, should try to establish tunnel.
16280 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1516281 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
16282 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1716283 "Proxy-Connection: keep-alive\r\n\r\n"),
16284
16285 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1516286 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1716287 "Connection: keep-alive\r\n\r\n"),
16288 };
16289
16290 MockRead data_reads1[] = {
16291 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16292
16293 MockRead("HTTP/1.1 200 OK\r\n"),
16294 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16295 MockRead("Content-Length: 100\r\n\r\n"),
16296 MockRead(SYNCHRONOUS, OK),
16297 };
16298
Ryan Sleevib8d7ea02018-05-07 20:01:0116299 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1716300 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16301 SSLSocketDataProvider ssl(ASYNC, OK);
16302 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16303
16304 TestCompletionCallback callback1;
16305
bnc691fda62016-08-12 00:43:1616306 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1716307
bnc691fda62016-08-12 00:43:1616308 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116309 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1716310
16311 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116312 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416313 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1716314 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016315 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16316 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716317 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016318 entries, pos,
16319 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16320 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716321
bnc691fda62016-08-12 00:43:1616322 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216323 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1716324
16325 EXPECT_TRUE(response->headers->IsKeepAlive());
16326 EXPECT_EQ(200, response->headers->response_code());
16327 EXPECT_EQ(100, response->headers->GetContentLength());
16328 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16329 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716330 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16331 HostPortPair::FromString("myproxy:70")),
16332 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1716333
16334 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616335 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1716336 TestLoadTimingNotReusedWithPac(load_timing_info,
16337 CONNECT_TIMING_HAS_SSL_TIMES);
16338}
16339
[email protected]76a505b2010-08-25 06:23:0016340// Test a basic HTTPS GET request through a proxy, but the server hangs up
16341// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0116342TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616343 session_deps_.proxy_resolution_service =
16344 ConfiguredProxyResolutionService::CreateFixed(
16345 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416346 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716347 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916348 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016349
[email protected]76a505b2010-08-25 06:23:0016350 HttpRequestInfo request;
16351 request.method = "GET";
bncce36dca22015-04-21 22:11:2316352 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016353 request.traffic_annotation =
16354 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016355
16356 // Since we have proxy, should try to establish tunnel.
16357 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716358 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16359 "Host: www.example.org:443\r\n"
16360 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016361
rsleevidb16bb02015-11-12 23:47:1716362 MockWrite("GET / HTTP/1.1\r\n"
16363 "Host: www.example.org\r\n"
16364 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016365 };
16366
16367 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0016368 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616369 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0016370 };
16371
Ryan Sleevib8d7ea02018-05-07 20:01:0116372 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716373 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616374 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716375 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016376
[email protected]49639fa2011-12-20 23:22:4116377 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016378
bnc691fda62016-08-12 00:43:1616379 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5016380
bnc691fda62016-08-12 00:43:1616381 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016383
16384 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116385 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5416386 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016387 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016388 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16389 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016390 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016391 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016392 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16393 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016394}
16395
[email protected]749eefa82010-09-13 22:14:0316396// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0116397TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1316398 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4916399 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116400 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0316401
Raul Tambre94493c652019-03-11 17:18:3516402 spdy::SpdySerializedFrame resp(
16403 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316404 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0316405 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116406 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0316407 };
16408
Ryan Sleevib8d7ea02018-05-07 20:01:0116409 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716410 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0316411
[email protected]8ddf8322012-02-23 18:08:0616412 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616413 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716414 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0316415
danakj1fd259a02016-04-16 03:17:0916416 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0316417
16418 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2316419 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4016420 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1116421 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3416422 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16423 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716424 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216425 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316426
16427 HttpRequestInfo request;
16428 request.method = "GET";
bncce36dca22015-04-21 22:11:2316429 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016430 request.traffic_annotation =
16431 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316432
bnc691fda62016-08-12 00:43:1616433 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316434
[email protected]41d64e82013-07-03 22:44:2616435 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016436 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116437 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16438 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316439}
16440
[email protected]73b8dd222010-11-11 19:55:2416441// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616442// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216443void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716444 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916445 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716446 request_info.url = GURL("https://www.example.com/");
16447 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916448 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016449 request_info.traffic_annotation =
16450 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716451
[email protected]8ddf8322012-02-23 18:08:0616452 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916453 MockWrite data_writes[] = {
16454 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416455 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116456 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716457 session_deps_.socket_factory->AddSocketDataProvider(&data);
16458 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416459
danakj1fd259a02016-04-16 03:17:0916460 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616461 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416462
[email protected]49639fa2011-12-20 23:22:4116463 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016464 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916465 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416466 rv = callback.WaitForResult();
16467 ASSERT_EQ(error, rv);
16468}
16469
bncd16676a2016-07-20 16:23:0116470TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416471 // Just check a grab bag of cert errors.
16472 static const int kErrors[] = {
16473 ERR_CERT_COMMON_NAME_INVALID,
16474 ERR_CERT_AUTHORITY_INVALID,
16475 ERR_CERT_DATE_INVALID,
16476 };
Avi Drissman4365a4782018-12-28 19:26:2416477 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616478 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16479 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416480 }
16481}
16482
[email protected]bd0b6772011-01-11 19:59:3016483// Ensure that a client certificate is removed from the SSL client auth
16484// cache when:
16485// 1) No proxy is involved.
16486// 2) TLS False Start is disabled.
16487// 3) The initial TLS handshake requests a client certificate.
16488// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116489TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916490 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716491 request_info.url = GURL("https://www.example.com/");
16492 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916493 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016494 request_info.traffic_annotation =
16495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716496
David Benjamin1c4b6d012019-07-08 17:12:5716497 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116498 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016499
16500 // [ssl_]data1 contains the data for the first SSL handshake. When a
16501 // CertificateRequest is received for the first time, the handshake will
16502 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916503 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016504 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716505 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116506 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716507 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016508
16509 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16510 // False Start is not being used, the result of the SSL handshake will be
16511 // returned as part of the SSLClientSocket::Connect() call. This test
16512 // matches the result of a server sending a handshake_failure alert,
16513 // rather than a Finished message, because it requires a client
16514 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916515 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016516 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116518 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716519 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016520
16521 // [ssl_]data3 contains the data for the third SSL handshake. When a
16522 // connection to a server fails during an SSL handshake,
David Benjamin07a07d652020-02-26 22:26:5916523 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
16524 // enabled on some errors. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016525 // of the HttpNetworkTransaction. Because this test failure is due to
16526 // requiring a client certificate, this fallback handshake should also
16527 // fail.
ttuttle859dc7a2015-04-23 19:42:2916528 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
David Benjamin07a07d652020-02-26 22:26:5916529 ssl_data3.expected_disable_legacy_crypto = false;
[email protected]bd0b6772011-01-11 19:59:3016530 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116532 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716533 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016534
danakj1fd259a02016-04-16 03:17:0916535 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616536 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016537
[email protected]bd0b6772011-01-11 19:59:3016538 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116539 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016540 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116541 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016542
16543 // Complete the SSL handshake, which should abort due to requiring a
16544 // client certificate.
16545 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116546 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016547
16548 // Indicate that no certificate should be supplied. From the perspective
16549 // of SSLClientCertCache, NULL is just as meaningful as a real
16550 // certificate, so this is the same as supply a
16551 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516552 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116553 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016554
16555 // Ensure the certificate was added to the client auth cache before
16556 // allowing the connection to continue restarting.
16557 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416558 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116559 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416560 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216561 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016562
16563 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716564 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16565 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016566 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116567 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016568
16569 // Ensure that the client certificate is removed from the cache on a
16570 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116571 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416572 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016573}
16574
16575// Ensure that a client certificate is removed from the SSL client auth
16576// cache when:
16577// 1) No proxy is involved.
16578// 2) TLS False Start is enabled.
16579// 3) The initial TLS handshake requests a client certificate.
16580// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116581TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916582 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716583 request_info.url = GURL("https://www.example.com/");
16584 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916585 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016586 request_info.traffic_annotation =
16587 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716588
David Benjamin1c4b6d012019-07-08 17:12:5716589 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116590 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016591
16592 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16593 // return successfully after reading up to the peer's Certificate message.
16594 // This is to allow the caller to call SSLClientSocket::Write(), which can
16595 // enqueue application data to be sent in the same packet as the
16596 // ChangeCipherSpec and Finished messages.
16597 // The actual handshake will be finished when SSLClientSocket::Read() is
16598 // called, which expects to process the peer's ChangeCipherSpec and
16599 // Finished messages. If there was an error negotiating with the peer,
16600 // such as due to the peer requiring a client certificate when none was
16601 // supplied, the alert sent by the peer won't be processed until Read() is
16602 // called.
16603
16604 // Like the non-False Start case, when a client certificate is requested by
16605 // the peer, the handshake is aborted during the Connect() call.
16606 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916607 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016608 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716609 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116610 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716611 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016612
16613 // When a client certificate is supplied, Connect() will not be aborted
16614 // when the peer requests the certificate. Instead, the handshake will
16615 // artificially succeed, allowing the caller to write the HTTP request to
16616 // the socket. The handshake messages are not processed until Read() is
16617 // called, which then detects that the handshake was aborted, due to the
16618 // peer sending a handshake_failure because it requires a client
16619 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916620 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016621 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916623 MockRead data2_reads[] = {
16624 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016625 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116626 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716627 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016628
16629 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716630 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16631 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916632 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016633 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716634 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116635 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716636 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016637
[email protected]80c75f682012-05-26 16:22:1716638 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16639 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916640 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716641 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716642 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116643 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716644 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716645
[email protected]7799de12013-05-30 05:52:5116646 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916647 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116648 ssl_data5.cert_request_info = cert_request.get();
16649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116650 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116651 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16652
danakj1fd259a02016-04-16 03:17:0916653 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616654 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016655
[email protected]bd0b6772011-01-11 19:59:3016656 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116657 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016658 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116659 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016660
16661 // Complete the SSL handshake, which should abort due to requiring a
16662 // client certificate.
16663 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116664 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016665
16666 // Indicate that no certificate should be supplied. From the perspective
16667 // of SSLClientCertCache, NULL is just as meaningful as a real
16668 // certificate, so this is the same as supply a
16669 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516670 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116671 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016672
16673 // Ensure the certificate was added to the client auth cache before
16674 // allowing the connection to continue restarting.
16675 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416676 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116677 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416678 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216679 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016680
[email protected]bd0b6772011-01-11 19:59:3016681 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716682 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16683 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016684 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116685 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016686
16687 // Ensure that the client certificate is removed from the cache on a
16688 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116689 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416690 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016691}
16692
[email protected]8c405132011-01-11 22:03:1816693// Ensure that a client certificate is removed from the SSL client auth
16694// cache when:
16695// 1) An HTTPS proxy is involved.
16696// 3) The HTTPS proxy requests a client certificate.
16697// 4) The client supplies an invalid/unacceptable certificate for the
16698// proxy.
bncd16676a2016-07-20 16:23:0116699TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616700 session_deps_.proxy_resolution_service =
16701 ConfiguredProxyResolutionService::CreateFixed(
16702 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416703 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716704 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816705
David Benjamin3b94b0f2019-04-25 23:07:5216706 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116707 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816708
David Benjamin3b94b0f2019-04-25 23:07:5216709 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16710 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916711 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816712 requests[0].url = GURL("https://www.example.com/");
16713 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916714 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016715 requests[0].traffic_annotation =
16716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816717
David Benjamin3b94b0f2019-04-25 23:07:5216718 // HTTPS requests are tunneled.
16719 MockWrite https_writes[] = {
16720 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16721 "Host: www.example.com:443\r\n"
16722 "Proxy-Connection: keep-alive\r\n\r\n"),
16723 };
16724
[email protected]8c405132011-01-11 22:03:1816725 requests[1].url = GURL("http://www.example.com/");
16726 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916727 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016728 requests[1].traffic_annotation =
16729 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816730
David Benjamin3b94b0f2019-04-25 23:07:5216731 // HTTP requests are not.
16732 MockWrite http_writes[] = {
16733 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16734 "Host: www.example.com\r\n"
16735 "Proxy-Connection: keep-alive\r\n\r\n"),
16736 };
[email protected]8c405132011-01-11 22:03:1816737
David Benjamin3b94b0f2019-04-25 23:07:5216738 // When the server rejects the client certificate, it will close the
16739 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16740 // TLS 1.2 with False Start), the error is returned out of the first Read().
16741 for (bool reject_in_connect : {true, false}) {
16742 SCOPED_TRACE(reject_in_connect);
16743 // Client certificate errors are typically signaled with
16744 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16745 // protocol error.
16746 for (Error reject_error :
16747 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16748 SCOPED_TRACE(reject_error);
16749 // Tunneled and non-tunneled requests are handled differently. Test both.
16750 for (const HttpRequestInfo& request : requests) {
16751 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816752
David Benjamin3b94b0f2019-04-25 23:07:5216753 session_deps_.socket_factory =
16754 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816755
David Benjamin3b94b0f2019-04-25 23:07:5216756 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
David Benjamin07a07d652020-02-26 22:26:5916757 // [ssl_]data[1-3].
David Benjamin3b94b0f2019-04-25 23:07:5216758 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16759 ssl_data1.cert_request_info = cert_request.get();
16760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16761 StaticSocketDataProvider data1;
16762 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816763
David Benjamin3b94b0f2019-04-25 23:07:5216764 base::Optional<SSLSocketDataProvider> ssl_data2;
16765 base::Optional<StaticSocketDataProvider> data2;
16766 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16767 if (reject_in_connect) {
16768 ssl_data2.emplace(ASYNC, reject_error);
16769 // There are no reads or writes.
16770 data2.emplace();
16771 } else {
16772 ssl_data2.emplace(ASYNC, OK);
16773 // We will get one Write() in before observing the error in Read().
16774 if (request.url.SchemeIsCryptographic()) {
16775 data2.emplace(error_in_read, https_writes);
16776 } else {
16777 data2.emplace(error_in_read, http_writes);
16778 }
16779 }
16780 ssl_data2->cert_request_info = cert_request.get();
David Benjamin3b94b0f2019-04-25 23:07:5216781 session_deps_.socket_factory->AddSSLSocketDataProvider(
16782 &ssl_data2.value());
16783 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816784
David Benjamin07a07d652020-02-26 22:26:5916785 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
16786 // connect twice.
16787 base::Optional<SSLSocketDataProvider> ssl_data3;
16788 base::Optional<StaticSocketDataProvider> data3;
16789 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
16790 ssl_data3.emplace(ASYNC, reject_error);
16791 data3.emplace(); // There are no reads or writes.
16792 ssl_data3->cert_request_info = cert_request.get();
16793 session_deps_.socket_factory->AddSSLSocketDataProvider(
16794 &ssl_data3.value());
16795 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
16796 }
16797
David Benjamin3b94b0f2019-04-25 23:07:5216798 std::unique_ptr<HttpNetworkSession> session =
16799 CreateSession(&session_deps_);
16800 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16801
16802 // Begin the SSL handshake with the proxy.
16803 TestCompletionCallback callback;
16804 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16805 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16806
16807 // Complete the SSL handshake, which should abort due to requiring a
16808 // client certificate.
16809 rv = callback.WaitForResult();
16810 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16811
16812 // Indicate that no certificate should be supplied. From the
16813 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16814 // real certificate, so this is the same as supply a
16815 // legitimate-but-unacceptable certificate.
16816 rv =
16817 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16818 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16819
16820 // Ensure the certificate was added to the client auth cache before
16821 // allowing the connection to continue restarting.
16822 scoped_refptr<X509Certificate> client_cert;
16823 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116824 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216825 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16826 ASSERT_FALSE(client_cert);
16827 // Ensure the certificate was NOT cached for the endpoint. This only
16828 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116829 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216830 HostPortPair("www.example.com", 443), &client_cert,
16831 &client_private_key));
16832
16833 // Restart the handshake. This will consume ssl_data2. The result code
16834 // is checked against what ssl_data2 should return.
16835 rv = callback.WaitForResult();
16836 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16837 IsError(reject_error)));
16838
16839 // Now that the new handshake has failed, ensure that the client
16840 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116841 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216842 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116843 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216844 HostPortPair("www.example.com", 443), &client_cert,
16845 &client_private_key));
16846 }
16847 }
[email protected]8c405132011-01-11 22:03:1816848 }
16849}
16850
David Benjamin1a0566082019-04-30 07:36:1916851// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16852// requests during a TLS renegotiation.
16853TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16854 HttpRequestInfo request_info;
16855 request_info.url = GURL("https://www.example.com/");
16856 request_info.method = "GET";
16857 request_info.load_flags = LOAD_NORMAL;
16858 request_info.traffic_annotation =
16859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16860
16861 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16862 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16863
16864 std::unique_ptr<FakeClientCertIdentity> identity =
16865 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16866 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16867 ASSERT_TRUE(identity);
16868
16869 // The first connection's handshake succeeds, but we get
16870 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16871 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16872 ssl_data1.cert_request_info = cert_request.get();
16873 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16874 MockWrite data1_writes[] = {
16875 MockWrite("GET / HTTP/1.1\r\n"
16876 "Host: www.example.com\r\n"
16877 "Connection: keep-alive\r\n\r\n"),
16878 };
16879 MockRead data1_reads[] = {
16880 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16881 };
16882 StaticSocketDataProvider data1(data1_reads, data1_writes);
16883 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16884
16885 // After supplying with certificate, we restart the request from the top,
16886 // which succeeds this time.
16887 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16888 ssl_data2.expected_send_client_cert = true;
16889 ssl_data2.expected_client_cert = identity->certificate();
16890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16891 MockWrite data2_writes[] = {
16892 MockWrite("GET / HTTP/1.1\r\n"
16893 "Host: www.example.com\r\n"
16894 "Connection: keep-alive\r\n\r\n"),
16895 };
16896 MockRead data2_reads[] = {
16897 MockRead("HTTP/1.1 200 OK\r\n"
16898 "Content-Length: 0\r\n\r\n"),
16899 };
16900 StaticSocketDataProvider data2(data2_reads, data2_writes);
16901 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16902
16903 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16904 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16905
16906 TestCompletionCallback callback;
16907 int rv = callback.GetResult(
16908 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16909 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16910
16911 rv = trans.RestartWithCertificate(identity->certificate(),
16912 identity->ssl_private_key(),
16913 callback.callback());
16914 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16915
16916 // Ensure the certificate was added to the client auth cache
16917 // allowing the connection to continue restarting.
16918 scoped_refptr<X509Certificate> client_cert;
16919 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116920 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916921 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16922 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16923
16924 // Complete the handshake. The request now succeeds.
16925 rv = callback.WaitForResult();
16926 ASSERT_THAT(rv, IsError(OK));
16927 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16928
16929 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116930 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916931 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16932 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16933}
16934
bncd16676a2016-07-20 16:23:0116935TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616936 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916937 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616939
bnc032658ba2016-09-26 18:17:1516940 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616941
Ryan Hamilton0239aac2018-05-19 00:03:1316942 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916943 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816944 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316945 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716946 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616947 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116948 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616949 };
Ryan Hamilton0239aac2018-05-19 00:03:1316950 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516951 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316952 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116953 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316954 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516955 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316956 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116957 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616958 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116959 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16960 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316961 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616962 };
16963
eroman36d84e54432016-03-17 03:23:0216964 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216965 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116966 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716967 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616968
[email protected]aa22b242011-11-16 18:58:2916969 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616970 HttpRequestInfo request1;
16971 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316972 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616973 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016974 request1.traffic_annotation =
16975 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016976 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616977
tfarina42834112016-09-22 13:38:2016978 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16980 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616981
16982 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216983 ASSERT_TRUE(response);
16984 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216985 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616986
16987 std::string response_data;
robpercival214763f2016-07-01 23:27:0116988 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616989 EXPECT_EQ("hello!", response_data);
16990
bnca4d611d2016-09-22 19:55:3716991 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316992 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316993 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16994 base::nullopt);
robpercival214763f2016-07-01 23:27:0116995 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616996
16997 HttpRequestInfo request2;
16998 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716999 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617000 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017001 request2.traffic_annotation =
17002 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017003 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617004
tfarina42834112016-09-22 13:38:2017005 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117006 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17007 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617008
17009 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217010 ASSERT_TRUE(response);
17011 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217012 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617013 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217014 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117015 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617016 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617017}
17018
bncd16676a2016-07-20 16:23:0117019TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0217020 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1917021 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0917022 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0217023
bnc032658ba2016-09-26 18:17:1517024 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0217025
Ryan Hamilton0239aac2018-05-19 00:03:1317026 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917027 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817028 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317029 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717030 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0217031 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117032 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0217033 };
Ryan Hamilton0239aac2018-05-19 00:03:1317034 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517035 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317036 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117037 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317038 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517039 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317040 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117041 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0217042 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117043 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17044 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317045 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0217046 };
17047
eroman36d84e54432016-03-17 03:23:0217048 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217049 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117050 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717051 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0217052
17053 TestCompletionCallback callback;
17054 HttpRequestInfo request1;
17055 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317056 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0217057 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017058 request1.traffic_annotation =
17059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017060 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217061
tfarina42834112016-09-22 13:38:2017062 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17064 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217065
17066 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217067 ASSERT_TRUE(response);
17068 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217069 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217070
17071 std::string response_data;
robpercival214763f2016-07-01 23:27:0117072 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217073 EXPECT_EQ("hello!", response_data);
17074
17075 HttpRequestInfo request2;
17076 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717077 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0217078 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017079 request2.traffic_annotation =
17080 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017081 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217082
tfarina42834112016-09-22 13:38:2017083 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117084 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17085 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217086
17087 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217088 ASSERT_TRUE(response);
17089 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217090 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217091 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217092 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117093 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217094 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0217095}
17096
bnc8016c1f2017-03-31 02:11:2917097// Regression test for https://crbug.com/546991.
17098// The server might not be able to serve an IP pooled request, and might send a
17099// 421 Misdirected Request response status to indicate this.
17100// HttpNetworkTransaction should reset the request and retry without IP pooling.
17101TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
17102 // Two hosts resolve to the same IP address.
17103 const std::string ip_addr = "1.2.3.4";
17104 IPAddress ip;
17105 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17106 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17107
Jeremy Roman0579ed62017-08-29 15:56:1917108 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2917109 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17110 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17111
17112 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17113
17114 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317115 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2917116 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17117 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317118 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2917119 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317120 spdy::SpdySerializedFrame rst(
17121 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2917122 MockWrite writes1[] = {
17123 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17124 CreateMockWrite(rst, 6),
17125 };
17126
17127 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317128 spdy::SpdySerializedFrame resp1(
17129 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17130 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0117131 spdy::Http2HeaderBlock response_headers;
Ryan Hamilton0239aac2018-05-19 00:03:1317132 response_headers[spdy::kHttp2StatusHeader] = "421";
17133 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2917134 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
17135 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17136 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17137
17138 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117139 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2917140 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17141
17142 AddSSLSocketData();
17143
17144 // Retry the second request on a second connection.
17145 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317146 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2917147 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17148 MockWrite writes2[] = {
17149 CreateMockWrite(req3, 0),
17150 };
17151
Ryan Hamilton0239aac2018-05-19 00:03:1317152 spdy::SpdySerializedFrame resp3(
17153 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
17154 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2917155 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17156 MockRead(ASYNC, 0, 3)};
17157
17158 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117159 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2917160 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17161
17162 AddSSLSocketData();
17163
17164 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317165 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317166 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17167 base::nullopt);
bnc8016c1f2017-03-31 02:11:2917168 EXPECT_THAT(rv, IsOk());
17169
17170 HttpRequestInfo request1;
17171 request1.method = "GET";
17172 request1.url = GURL("https://www.example.org/");
17173 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017174 request1.traffic_annotation =
17175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917176 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17177
Eric Orthf4db66a2019-02-19 21:35:3317178 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2917179 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17180 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17181 rv = callback.WaitForResult();
17182 EXPECT_THAT(rv, IsOk());
17183
17184 const HttpResponseInfo* response = trans1.GetResponseInfo();
17185 ASSERT_TRUE(response);
17186 ASSERT_TRUE(response->headers);
17187 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17188 EXPECT_TRUE(response->was_fetched_via_spdy);
17189 EXPECT_TRUE(response->was_alpn_negotiated);
17190 std::string response_data;
17191 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17192 EXPECT_EQ("hello!", response_data);
17193
17194 HttpRequestInfo request2;
17195 request2.method = "GET";
17196 request2.url = GURL("https://mail.example.org/");
17197 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017198 request2.traffic_annotation =
17199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917200 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17201
Matt Muellerd9342e3a2019-11-26 01:41:1417202 RecordingBoundTestNetLog log;
bnc8016c1f2017-03-31 02:11:2917203 rv = trans2.Start(&request2, callback.callback(), log.bound());
17204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17205 rv = callback.WaitForResult();
17206 EXPECT_THAT(rv, IsOk());
17207
17208 response = trans2.GetResponseInfo();
17209 ASSERT_TRUE(response);
17210 ASSERT_TRUE(response->headers);
17211 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17212 EXPECT_TRUE(response->was_fetched_via_spdy);
17213 EXPECT_TRUE(response->was_alpn_negotiated);
17214 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17215 EXPECT_EQ("hello!", response_data);
17216
Eric Roman79cc7552019-07-19 02:17:5417217 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5917218 ExpectLogContainsSomewhere(
17219 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2917220 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5917221}
17222
17223// Test that HTTP 421 responses are properly returned to the caller if received
17224// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
17225// portions of the response.
17226TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
17227 // Two hosts resolve to the same IP address.
17228 const std::string ip_addr = "1.2.3.4";
17229 IPAddress ip;
17230 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17231 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17232
Jeremy Roman0579ed62017-08-29 15:56:1917233 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5917234 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17235 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17236
17237 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17238
17239 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317240 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5917241 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17242 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317243 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5917244 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317245 spdy::SpdySerializedFrame rst(
17246 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5917247 MockWrite writes1[] = {
17248 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17249 CreateMockWrite(rst, 6),
17250 };
17251
17252 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317253 spdy::SpdySerializedFrame resp1(
17254 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17255 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0117256 spdy::Http2HeaderBlock response_headers;
Ryan Hamilton0239aac2018-05-19 00:03:1317257 response_headers[spdy::kHttp2StatusHeader] = "421";
17258 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5917259 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
17260 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17261 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17262
17263 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117264 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5917265 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17266
17267 AddSSLSocketData();
17268
17269 // Retry the second request on a second connection. It returns 421 Misdirected
17270 // Retry again.
17271 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317272 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5917273 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17274 MockWrite writes2[] = {
17275 CreateMockWrite(req3, 0),
17276 };
17277
Ryan Hamilton0239aac2018-05-19 00:03:1317278 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5917279 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1317280 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5917281 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17282 MockRead(ASYNC, 0, 3)};
17283
17284 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117285 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5917286 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17287
17288 AddSSLSocketData();
17289
17290 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317291 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317292 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17293 base::nullopt);
davidbence688ae2017-05-04 15:12:5917294 EXPECT_THAT(rv, IsOk());
17295
17296 HttpRequestInfo request1;
17297 request1.method = "GET";
17298 request1.url = GURL("https://www.example.org/");
17299 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017300 request1.traffic_annotation =
17301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917302 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17303
Eric Orthf4db66a2019-02-19 21:35:3317304 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5917305 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17306 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17307 rv = callback.WaitForResult();
17308 EXPECT_THAT(rv, IsOk());
17309
17310 const HttpResponseInfo* response = trans1.GetResponseInfo();
17311 ASSERT_TRUE(response);
17312 ASSERT_TRUE(response->headers);
17313 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17314 EXPECT_TRUE(response->was_fetched_via_spdy);
17315 EXPECT_TRUE(response->was_alpn_negotiated);
17316 std::string response_data;
17317 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17318 EXPECT_EQ("hello!", response_data);
17319
17320 HttpRequestInfo request2;
17321 request2.method = "GET";
17322 request2.url = GURL("https://mail.example.org/");
17323 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017324 request2.traffic_annotation =
17325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917326 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17327
Matt Muellerd9342e3a2019-11-26 01:41:1417328 RecordingBoundTestNetLog log;
davidbence688ae2017-05-04 15:12:5917329 rv = trans2.Start(&request2, callback.callback(), log.bound());
17330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17331 rv = callback.WaitForResult();
17332 EXPECT_THAT(rv, IsOk());
17333
17334 // After a retry, the 421 Misdirected Request is reported back up to the
17335 // caller.
17336 response = trans2.GetResponseInfo();
17337 ASSERT_TRUE(response);
17338 ASSERT_TRUE(response->headers);
17339 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
17340 EXPECT_TRUE(response->was_fetched_via_spdy);
17341 EXPECT_TRUE(response->was_alpn_negotiated);
17342 EXPECT_TRUE(response->ssl_info.cert);
17343 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17344 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2917345}
17346
bncd16676a2016-07-20 16:23:0117347TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1317348 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3417349 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
17350 session_deps_.host_resolver =
17351 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0917352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617353
bnc032658ba2016-09-26 18:17:1517354 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617355
Ryan Hamilton0239aac2018-05-19 00:03:1317356 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917357 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817358 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317359 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717360 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617361 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117362 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617363 };
Ryan Hamilton0239aac2018-05-19 00:03:1317364 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517365 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317366 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117367 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317368 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517369 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317370 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117371 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617372 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117373 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17374 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317375 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617376 };
17377
eroman36d84e54432016-03-17 03:23:0217378 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217379 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117380 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717381 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617382
[email protected]aa22b242011-11-16 18:58:2917383 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617384 HttpRequestInfo request1;
17385 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317386 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617387 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017388 request1.traffic_annotation =
17389 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017390 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617391
tfarina42834112016-09-22 13:38:2017392 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17394 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617395
17396 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217397 ASSERT_TRUE(response);
17398 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217399 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617400
17401 std::string response_data;
robpercival214763f2016-07-01 23:27:0117402 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617403 EXPECT_EQ("hello!", response_data);
17404
17405 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317406 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317407 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17408 base::nullopt);
robpercival214763f2016-07-01 23:27:0117409 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617410
17411 HttpRequestInfo request2;
17412 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717413 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617414 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017415 request2.traffic_annotation =
17416 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017417 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617418
tfarina42834112016-09-22 13:38:2017419 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17421 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617422
17423 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217424 ASSERT_TRUE(response);
17425 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217426 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617427 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217428 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117429 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617430 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617431}
17432
bncd16676a2016-07-20 16:23:0117433TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317434 const std::string https_url = "https://www.example.org:8080/";
17435 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417436
17437 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317438 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917439 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417440
17441 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117442 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417443 };
17444
Raul Tambre94493c652019-03-11 17:18:3517445 spdy::SpdySerializedFrame resp1(
17446 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317447 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117448 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917449 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417450
Ryan Sleevib8d7ea02018-05-07 20:01:0117451 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417452 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717453 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417454
17455 // HTTP GET for the HTTP URL
17456 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317457 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417458 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317459 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417460 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417461 };
17462
17463 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317464 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17465 MockRead(ASYNC, 2, "hello"),
17466 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417467 };
17468
Ryan Sleevib8d7ea02018-05-07 20:01:0117469 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417470
[email protected]8450d722012-07-02 19:14:0417471 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617472 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17474 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17475 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417476
danakj1fd259a02016-04-16 03:17:0917477 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417478
17479 // Start the first transaction to set up the SpdySession
17480 HttpRequestInfo request1;
17481 request1.method = "GET";
17482 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417483 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017484 request1.traffic_annotation =
17485 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017486 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417487 TestCompletionCallback callback1;
17488 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017489 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517490 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417491
robpercival214763f2016-07-01 23:27:0117492 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417493 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17494
17495 // Now, start the HTTP request
17496 HttpRequestInfo request2;
17497 request2.method = "GET";
17498 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417499 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017500 request2.traffic_annotation =
17501 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017502 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417503 TestCompletionCallback callback2;
17504 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017505 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517506 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417507
robpercival214763f2016-07-01 23:27:0117508 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417509 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17510}
17511
bnc5452e2a2015-05-08 16:27:4217512// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17513// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117514TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517515 url::SchemeHostPort server("https", "www.example.org", 443);
17516 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217517
bnc8bef8da22016-05-30 01:28:2517518 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217519 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617520 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217521 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17522
17523 // No data should be read from the alternative, because HTTP/1.1 is
17524 // negotiated.
17525 StaticSocketDataProvider data;
17526 session_deps_.socket_factory->AddSocketDataProvider(&data);
17527
17528 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617529 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217530 // mocked. This way the request relies on the alternate Job.
17531 StaticSocketDataProvider data_refused;
17532 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17533 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17534
zhongyi3d4a55e72016-04-22 20:36:4617535 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917536 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017537 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217538 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117539 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217540 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117541 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717542 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217543
bnc5452e2a2015-05-08 16:27:4217544 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217546 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517547 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1017548 request.traffic_annotation =
17549 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217550 TestCompletionCallback callback;
17551
17552 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217553 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017554 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217555 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217556}
17557
bnc40448a532015-05-11 19:13:1417558// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617559// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417560// succeeds, the request should succeed, even if the latter fails because
17561// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117562TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517563 url::SchemeHostPort server("https", "www.example.org", 443);
17564 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417565
17566 // Negotiate HTTP/1.1 with alternative.
17567 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617568 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417569 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17570
17571 // No data should be read from the alternative, because HTTP/1.1 is
17572 // negotiated.
17573 StaticSocketDataProvider data;
17574 session_deps_.socket_factory->AddSocketDataProvider(&data);
17575
zhongyi3d4a55e72016-04-22 20:36:4617576 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417577 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617578 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417579 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17580
17581 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517582 MockWrite("GET / HTTP/1.1\r\n"
17583 "Host: www.example.org\r\n"
17584 "Connection: keep-alive\r\n\r\n"),
17585 MockWrite("GET /second HTTP/1.1\r\n"
17586 "Host: www.example.org\r\n"
17587 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417588 };
17589
17590 MockRead http_reads[] = {
17591 MockRead("HTTP/1.1 200 OK\r\n"),
17592 MockRead("Content-Type: text/html\r\n"),
17593 MockRead("Content-Length: 6\r\n\r\n"),
17594 MockRead("foobar"),
17595 MockRead("HTTP/1.1 200 OK\r\n"),
17596 MockRead("Content-Type: text/html\r\n"),
17597 MockRead("Content-Length: 7\r\n\r\n"),
17598 MockRead("another"),
17599 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117600 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417601 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17602
zhongyi3d4a55e72016-04-22 20:36:4617603 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917604 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017605 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417606 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117607 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217608 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117609 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717610 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417611
17612 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17613 HttpRequestInfo request1;
17614 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517615 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417616 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017617 request1.traffic_annotation =
17618 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417619 TestCompletionCallback callback1;
17620
tfarina42834112016-09-22 13:38:2017621 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417622 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117623 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417624
17625 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217626 ASSERT_TRUE(response1);
17627 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417628 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17629
17630 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117631 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417632 EXPECT_EQ("foobar", response_data1);
17633
17634 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17635 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517636 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17637 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417638
zhongyi3d4a55e72016-04-22 20:36:4617639 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417640 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617641 // to server.
bnc40448a532015-05-11 19:13:1417642 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17643 HttpRequestInfo request2;
17644 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517645 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417646 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017647 request2.traffic_annotation =
17648 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417649 TestCompletionCallback callback2;
17650
tfarina42834112016-09-22 13:38:2017651 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417652 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117653 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417654
17655 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217656 ASSERT_TRUE(response2);
17657 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417658 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17659
17660 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117661 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417662 EXPECT_EQ("another", response_data2);
17663}
17664
bnc5452e2a2015-05-08 16:27:4217665// Alternative service requires HTTP/2 (or SPDY), but there is already a
17666// HTTP/1.1 socket open to the alternative server. That socket should not be
17667// used.
bncd16676a2016-07-20 16:23:0117668TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617669 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217670 HostPortPair alternative("alternative.example.org", 443);
17671 std::string origin_url = "https://origin.example.org:443";
17672 std::string alternative_url = "https://alternative.example.org:443";
17673
17674 // Negotiate HTTP/1.1 with alternative.example.org.
17675 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617676 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217677 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17678
17679 // HTTP/1.1 data for |request1| and |request2|.
17680 MockWrite http_writes[] = {
17681 MockWrite(
17682 "GET / HTTP/1.1\r\n"
17683 "Host: alternative.example.org\r\n"
17684 "Connection: keep-alive\r\n\r\n"),
17685 MockWrite(
17686 "GET / HTTP/1.1\r\n"
17687 "Host: alternative.example.org\r\n"
17688 "Connection: keep-alive\r\n\r\n"),
17689 };
17690
17691 MockRead http_reads[] = {
17692 MockRead(
17693 "HTTP/1.1 200 OK\r\n"
17694 "Content-Type: text/html; charset=iso-8859-1\r\n"
17695 "Content-Length: 40\r\n\r\n"
17696 "first HTTP/1.1 response from alternative"),
17697 MockRead(
17698 "HTTP/1.1 200 OK\r\n"
17699 "Content-Type: text/html; charset=iso-8859-1\r\n"
17700 "Content-Length: 41\r\n\r\n"
17701 "second HTTP/1.1 response from alternative"),
17702 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117703 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217704 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17705
17706 // This test documents that an alternate Job should not pool to an already
17707 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617708 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217709 StaticSocketDataProvider data_refused;
17710 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17711 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17712
zhongyi3d4a55e72016-04-22 20:36:4617713 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917714 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017715 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217716 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117717 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217718 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117719 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717720 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217721
17722 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217723 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617724 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217725 request1.method = "GET";
17726 request1.url = GURL(alternative_url);
17727 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017728 request1.traffic_annotation =
17729 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217730 TestCompletionCallback callback1;
17731
tfarina42834112016-09-22 13:38:2017732 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117733 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617734 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217735 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217736 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217737 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217738 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217739 EXPECT_FALSE(response1->was_fetched_via_spdy);
17740 std::string response_data1;
bnc691fda62016-08-12 00:43:1617741 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217742 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17743
17744 // Request for origin.example.org, which has an alternative service. This
17745 // will start two Jobs: the alternative looks for connections to pool to,
17746 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617747 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217748 // this request fails.
bnc5452e2a2015-05-08 16:27:4217749 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617750 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217751 request2.method = "GET";
17752 request2.url = GURL(origin_url);
17753 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017754 request2.traffic_annotation =
17755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217756 TestCompletionCallback callback2;
17757
tfarina42834112016-09-22 13:38:2017758 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117759 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217760
17761 // Another transaction to alternative. This is to test that the HTTP/1.1
17762 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217763 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617764 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217765 request3.method = "GET";
17766 request3.url = GURL(alternative_url);
17767 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017768 request3.traffic_annotation =
17769 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217770 TestCompletionCallback callback3;
17771
tfarina42834112016-09-22 13:38:2017772 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117773 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617774 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217775 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217776 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217777 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217778 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217779 EXPECT_FALSE(response3->was_fetched_via_spdy);
17780 std::string response_data3;
bnc691fda62016-08-12 00:43:1617781 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217782 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17783}
17784
bncd16676a2016-07-20 16:23:0117785TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317786 const std::string https_url = "https://www.example.org:8080/";
17787 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417788
rdsmithebb50aa2015-11-12 03:44:3817789 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117790 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817791
[email protected]8450d722012-07-02 19:14:0417792 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317793 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417794 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17795 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17796 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317797 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917798 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317799 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217800 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917801
17802 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Bence Béky4c325e52020-10-22 20:48:0117803 spdy::Http2HeaderBlock req2_block;
Ryan Hamilton0239aac2018-05-19 00:03:1317804 req2_block[spdy::kHttp2MethodHeader] = "GET";
17805 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17806 req2_block[spdy::kHttp2SchemeHeader] = "http";
17807 req2_block[spdy::kHttp2PathHeader] = "/";
17808 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517809 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417810
17811 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117812 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17813 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417814 };
17815
Ryan Hamilton0239aac2018-05-19 00:03:1317816 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517817 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317818 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517819 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317820 spdy::SpdySerializedFrame body1(
17821 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17822 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817823 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317824 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817825 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517826 spdy::SpdySerializedFrame resp2(
17827 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317828 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317829 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117830 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317831 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117832 CreateMockRead(wrapped_resp1, 4),
17833 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317834 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117835 CreateMockRead(resp2, 8),
17836 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317837 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17838 };
[email protected]8450d722012-07-02 19:14:0417839
Ryan Sleevib8d7ea02018-05-07 20:01:0117840 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417841 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717842 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417843
Lily Houghton8c2f97d2018-01-22 05:06:5917844 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617845 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4917846 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1417847 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717848 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417849 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617850 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417852 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617853 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317854 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17855 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417856
danakj1fd259a02016-04-16 03:17:0917857 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417858
17859 // Start the first transaction to set up the SpdySession
17860 HttpRequestInfo request1;
17861 request1.method = "GET";
17862 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417863 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017864 request1.traffic_annotation =
17865 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017866 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417867 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017868 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417869
mmenke666a6fea2015-12-19 04:16:3317870 // This pause is a hack to avoid running into https://crbug.com/497228.
17871 data1.RunUntilPaused();
17872 base::RunLoop().RunUntilIdle();
17873 data1.Resume();
robpercival214763f2016-07-01 23:27:0117874 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417875 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17876
[email protected]f6c63db52013-02-02 00:35:2217877 LoadTimingInfo load_timing_info1;
17878 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17879 TestLoadTimingNotReusedWithPac(load_timing_info1,
17880 CONNECT_TIMING_HAS_SSL_TIMES);
17881
mmenke666a6fea2015-12-19 04:16:3317882 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417883 HttpRequestInfo request2;
17884 request2.method = "GET";
17885 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417886 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017887 request2.traffic_annotation =
17888 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017889 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417890 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017891 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417892
mmenke666a6fea2015-12-19 04:16:3317893 // This pause is a hack to avoid running into https://crbug.com/497228.
17894 data1.RunUntilPaused();
17895 base::RunLoop().RunUntilIdle();
17896 data1.Resume();
robpercival214763f2016-07-01 23:27:0117897 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317898
[email protected]8450d722012-07-02 19:14:0417899 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217900
17901 LoadTimingInfo load_timing_info2;
17902 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17903 // The established SPDY sessions is considered reused by the HTTP request.
17904 TestLoadTimingReusedWithPac(load_timing_info2);
17905 // HTTP requests over a SPDY session should have a different connection
17906 // socket_log_id than requests over a tunnel.
17907 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417908}
17909
[email protected]2d88e7d2012-07-19 17:55:1717910// Test that in the case where we have a SPDY session to a SPDY proxy
17911// that we do not pool other origins that resolve to the same IP when
17912// the certificate does not match the new origin.
17913// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117914TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317915 const std::string url1 = "http://www.example.org/";
17916 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717917 const std::string ip_addr = "1.2.3.4";
17918
rdsmithebb50aa2015-11-12 03:44:3817919 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117920 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817921
[email protected]2d88e7d2012-07-19 17:55:1717922 // SPDY GET for HTTP URL (through SPDY proxy)
Bence Béky4c325e52020-10-22 20:48:0117923 spdy::Http2HeaderBlock headers(
bncce36dca22015-04-21 22:11:2317924 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317925 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517926 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717927
17928 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117929 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717930 };
17931
Raul Tambre94493c652019-03-11 17:18:3517932 spdy::SpdySerializedFrame resp1(
17933 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317934 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717935 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117936 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17937 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717938 };
17939
Ryan Sleevib8d7ea02018-05-07 20:01:0117940 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217941 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917942 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717943 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17944 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317945 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717946
17947 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317948 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917949 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717950
17951 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117952 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717953 };
17954
Ryan Hamilton0239aac2018-05-19 00:03:1317955 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517956 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317957 spdy::SpdySerializedFrame body2(
17958 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117959 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317960 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717961
Ryan Sleevib8d7ea02018-05-07 20:01:0117962 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717963 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317964 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717965
17966 // Set up a proxy config that sends HTTP requests to a proxy, and
17967 // all others direct.
17968 ProxyConfig proxy_config;
17969 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917970 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617971 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4917972 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17973 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0917974 nullptr, nullptr, /*quick_check_enabled=*/true);
[email protected]2d88e7d2012-07-19 17:55:1717975
bncce36dca22015-04-21 22:11:2317976 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617977 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717978 // Load a valid cert. Note, that this does not need to
17979 // be valid for proxy because the MockSSLClientSocket does
17980 // not actually verify it. But SpdySession will use this
17981 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917982 ssl1.ssl_info.cert =
17983 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17984 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317985 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17986 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717987
17988 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617989 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317990 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17991 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717992
Jeremy Roman0579ed62017-08-29 15:56:1917993 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317994 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717995 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717996
danakj1fd259a02016-04-16 03:17:0917997 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717998
17999 // Start the first transaction to set up the SpdySession
18000 HttpRequestInfo request1;
18001 request1.method = "GET";
18002 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1718003 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018004 request1.traffic_annotation =
18005 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018006 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718007 TestCompletionCallback callback1;
18008 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018009 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3318010 // This pause is a hack to avoid running into https://crbug.com/497228.
18011 data1.RunUntilPaused();
18012 base::RunLoop().RunUntilIdle();
18013 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1718014
robpercival214763f2016-07-01 23:27:0118015 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718016 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
18017
18018 // Now, start the HTTP request
18019 HttpRequestInfo request2;
18020 request2.method = "GET";
18021 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1718022 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018023 request2.traffic_annotation =
18024 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018025 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718026 TestCompletionCallback callback2;
18027 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018028 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5518029 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1718030
18031 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0118032 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718033 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18034}
18035
[email protected]85f97342013-04-17 06:12:2418036// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
18037// error) in SPDY session, removes the socket from pool and closes the SPDY
18038// session. Verify that new url's from the same HttpNetworkSession (and a new
18039// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0118040TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2318041 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2418042
18043 MockRead reads1[] = {
18044 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
18045 };
18046
Ryan Sleevib8d7ea02018-05-07 20:01:0118047 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2418048
Ryan Hamilton0239aac2018-05-19 00:03:1318049 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4918050 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2418051 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4118052 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2418053 };
18054
Raul Tambre94493c652019-03-11 17:18:3518055 spdy::SpdySerializedFrame resp2(
18056 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318057 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2418058 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4118059 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
18060 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2418061 };
18062
Ryan Sleevib8d7ea02018-05-07 20:01:0118063 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2418064
[email protected]85f97342013-04-17 06:12:2418065 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618066 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018067 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2418069
18070 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618071 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018072 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18073 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2418074
danakj1fd259a02016-04-16 03:17:0918075 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5018076 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2418077
18078 // Start the first transaction to set up the SpdySession and verify that
18079 // connection was closed.
18080 HttpRequestInfo request1;
18081 request1.method = "GET";
18082 request1.url = GURL(https_url);
18083 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018084 request1.traffic_annotation =
18085 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018086 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418087 TestCompletionCallback callback1;
18088 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018089 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118090 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2418091
18092 // Now, start the second request and make sure it succeeds.
18093 HttpRequestInfo request2;
18094 request2.method = "GET";
18095 request2.url = GURL(https_url);
18096 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018097 request2.traffic_annotation =
18098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018099 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418100 TestCompletionCallback callback2;
18101 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018102 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2418103
robpercival214763f2016-07-01 23:27:0118104 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2418105 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18106}
18107
bncd16676a2016-07-20 16:23:0118108TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0318109 ClientSocketPoolManager::set_max_sockets_per_group(
18110 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18111 ClientSocketPoolManager::set_max_sockets_per_pool(
18112 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18113
18114 // Use two different hosts with different IPs so they don't get pooled.
18115 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
18116 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0918117 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0318118
18119 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618120 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318121 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618122 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318123 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18124 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18125
Ryan Hamilton0239aac2018-05-19 00:03:1318126 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4918127 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318128 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118129 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0318130 };
Ryan Hamilton0239aac2018-05-19 00:03:1318131 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3518132 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318133 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4118134 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318135 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118136 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918137 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318138 };
18139
rdsmithebb50aa2015-11-12 03:44:3818140 // Use a separate test instance for the separate SpdySession that will be
18141 // created.
bncd16676a2016-07-20 16:23:0118142 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0118143 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1218144 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0318145
Ryan Hamilton0239aac2018-05-19 00:03:1318146 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4918147 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318148 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118149 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0318150 };
Ryan Hamilton0239aac2018-05-19 00:03:1318151 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3518152 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318153 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4118154 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318155 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118156 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918157 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318158 };
18159
Ryan Sleevib8d7ea02018-05-07 20:01:0118160 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1218161 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0318162
18163 MockWrite http_write[] = {
18164 MockWrite("GET / HTTP/1.1\r\n"
18165 "Host: www.a.com\r\n"
18166 "Connection: keep-alive\r\n\r\n"),
18167 };
18168
18169 MockRead http_read[] = {
18170 MockRead("HTTP/1.1 200 OK\r\n"),
18171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18172 MockRead("Content-Length: 6\r\n\r\n"),
18173 MockRead("hello!"),
18174 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118175 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0318176 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18177
18178 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118179 SpdySessionKey spdy_session_key_a(
18180 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418181 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18182 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318183 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618184 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318185
18186 TestCompletionCallback callback;
18187 HttpRequestInfo request1;
18188 request1.method = "GET";
18189 request1.url = GURL("https://www.a.com/");
18190 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018191 request1.traffic_annotation =
18192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818193 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918194 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318195
tfarina42834112016-09-22 13:38:2018196 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118197 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18198 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318199
18200 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218201 ASSERT_TRUE(response);
18202 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218203 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318204 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218205 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0318206
18207 std::string response_data;
robpercival214763f2016-07-01 23:27:0118208 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318209 EXPECT_EQ("hello!", response_data);
18210 trans.reset();
18211 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618212 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318213
18214 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118215 SpdySessionKey spdy_session_key_b(
18216 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418217 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18218 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318219 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618220 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318221 HttpRequestInfo request2;
18222 request2.method = "GET";
18223 request2.url = GURL("https://www.b.com/");
18224 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018225 request2.traffic_annotation =
18226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818227 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918228 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318229
tfarina42834112016-09-22 13:38:2018230 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118231 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18232 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318233
18234 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218235 ASSERT_TRUE(response);
18236 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218237 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318238 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218239 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118240 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318241 EXPECT_EQ("hello!", response_data);
18242 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618243 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318244 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618245 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318246
18247 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1118248 SpdySessionKey spdy_session_key_a1(
18249 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418250 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18251 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318252 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618253 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0318254 HttpRequestInfo request3;
18255 request3.method = "GET";
18256 request3.url = GURL("http://www.a.com/");
18257 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018258 request3.traffic_annotation =
18259 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818260 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918261 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318262
tfarina42834112016-09-22 13:38:2018263 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18265 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318266
18267 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218268 ASSERT_TRUE(response);
18269 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0318270 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
18271 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218272 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118273 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318274 EXPECT_EQ("hello!", response_data);
18275 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618276 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318277 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618278 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318279}
18280
bncd16676a2016-07-20 16:23:0118281TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418282 HttpRequestInfo request;
18283 request.method = "GET";
bncce36dca22015-04-21 22:11:2318284 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018285 request.traffic_annotation =
18286 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418287
danakj1fd259a02016-04-16 03:17:0918288 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618289 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418290
ttuttled9dbc652015-09-29 20:00:5918291 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418292 StaticSocketDataProvider data;
18293 data.set_connect_data(mock_connect);
18294 session_deps_.socket_factory->AddSocketDataProvider(&data);
18295
18296 TestCompletionCallback callback;
18297
tfarina42834112016-09-22 13:38:2018298 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118299 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418300
18301 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118302 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418303
ttuttle1f2d7e92015-04-28 16:17:4718304 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618305 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718306 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118307 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918308
18309 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618310 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918311 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418312}
18313
bncd16676a2016-07-20 16:23:0118314TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418315 HttpRequestInfo request;
18316 request.method = "GET";
bncce36dca22015-04-21 22:11:2318317 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018318 request.traffic_annotation =
18319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418320
danakj1fd259a02016-04-16 03:17:0918321 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618322 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418323
ttuttled9dbc652015-09-29 20:00:5918324 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418325 StaticSocketDataProvider data;
18326 data.set_connect_data(mock_connect);
18327 session_deps_.socket_factory->AddSocketDataProvider(&data);
18328
18329 TestCompletionCallback callback;
18330
tfarina42834112016-09-22 13:38:2018331 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118332 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418333
18334 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118335 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418336
ttuttle1f2d7e92015-04-28 16:17:4718337 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618338 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718339 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118340 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918341
18342 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618343 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918344 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418345}
18346
bncd16676a2016-07-20 16:23:0118347TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418348 HttpRequestInfo request;
18349 request.method = "GET";
bncce36dca22015-04-21 22:11:2318350 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018351 request.traffic_annotation =
18352 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418353
danakj1fd259a02016-04-16 03:17:0918354 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418356
18357 MockWrite data_writes[] = {
18358 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18359 };
18360 MockRead data_reads[] = {
18361 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18362 };
18363
Ryan Sleevib8d7ea02018-05-07 20:01:0118364 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418365 session_deps_.socket_factory->AddSocketDataProvider(&data);
18366
18367 TestCompletionCallback callback;
18368
tfarina42834112016-09-22 13:38:2018369 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418371
18372 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118373 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418374}
18375
bncd16676a2016-07-20 16:23:0118376TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418377 HttpRequestInfo request;
18378 request.method = "GET";
bncce36dca22015-04-21 22:11:2318379 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018380 request.traffic_annotation =
18381 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418382
danakj1fd259a02016-04-16 03:17:0918383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618384 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418385
18386 MockWrite data_writes[] = {
18387 MockWrite(ASYNC, ERR_CONNECTION_RESET),
18388 };
18389 MockRead data_reads[] = {
18390 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18391 };
18392
Ryan Sleevib8d7ea02018-05-07 20:01:0118393 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418394 session_deps_.socket_factory->AddSocketDataProvider(&data);
18395
18396 TestCompletionCallback callback;
18397
tfarina42834112016-09-22 13:38:2018398 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118399 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418400
18401 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118402 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418403}
18404
bncd16676a2016-07-20 16:23:0118405TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418406 HttpRequestInfo request;
18407 request.method = "GET";
bncce36dca22015-04-21 22:11:2318408 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018409 request.traffic_annotation =
18410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418411
danakj1fd259a02016-04-16 03:17:0918412 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418414
18415 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318416 MockWrite(
18417 "GET / HTTP/1.1\r\n"
18418 "Host: www.example.org\r\n"
18419 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418420 };
18421 MockRead data_reads[] = {
18422 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18423 };
18424
Ryan Sleevib8d7ea02018-05-07 20:01:0118425 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418426 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_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418435}
18436
bncd16676a2016-07-20 16:23:0118437TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418438 HttpRequestInfo request;
18439 request.method = "GET";
bncce36dca22015-04-21 22:11:2318440 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018441 request.traffic_annotation =
18442 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418443
danakj1fd259a02016-04-16 03:17:0918444 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618445 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418446
18447 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318448 MockWrite(
18449 "GET / HTTP/1.1\r\n"
18450 "Host: www.example.org\r\n"
18451 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418452 };
18453 MockRead data_reads[] = {
18454 MockRead(ASYNC, ERR_CONNECTION_RESET),
18455 };
18456
Ryan Sleevib8d7ea02018-05-07 20:01:0118457 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418458 session_deps_.socket_factory->AddSocketDataProvider(&data);
18459
18460 TestCompletionCallback callback;
18461
tfarina42834112016-09-22 13:38:2018462 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418464
18465 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118466 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418467}
18468
[email protected]043b68c82013-08-22 23:41:5218469// Tests that when a used socket is returned to the SSL socket pool, it's closed
18470// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118471TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218472 ClientSocketPoolManager::set_max_sockets_per_group(
18473 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18474 ClientSocketPoolManager::set_max_sockets_per_pool(
18475 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18476
18477 // Set up SSL request.
18478
18479 HttpRequestInfo ssl_request;
18480 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318481 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018482 ssl_request.traffic_annotation =
18483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218484
18485 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318486 MockWrite(
18487 "GET / HTTP/1.1\r\n"
18488 "Host: www.example.org\r\n"
18489 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218490 };
18491 MockRead ssl_reads[] = {
18492 MockRead("HTTP/1.1 200 OK\r\n"),
18493 MockRead("Content-Length: 11\r\n\r\n"),
18494 MockRead("hello world"),
18495 MockRead(SYNCHRONOUS, OK),
18496 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118497 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218498 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18499
18500 SSLSocketDataProvider ssl(ASYNC, OK);
18501 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18502
18503 // Set up HTTP request.
18504
18505 HttpRequestInfo http_request;
18506 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318507 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018508 http_request.traffic_annotation =
18509 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218510
18511 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318512 MockWrite(
18513 "GET / HTTP/1.1\r\n"
18514 "Host: www.example.org\r\n"
18515 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218516 };
18517 MockRead http_reads[] = {
18518 MockRead("HTTP/1.1 200 OK\r\n"),
18519 MockRead("Content-Length: 7\r\n\r\n"),
18520 MockRead("falafel"),
18521 MockRead(SYNCHRONOUS, OK),
18522 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118523 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218524 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18525
danakj1fd259a02016-04-16 03:17:0918526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218527
18528 // Start the SSL request.
18529 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618530 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018531 ASSERT_EQ(ERR_IO_PENDING,
18532 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18533 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218534
18535 // Start the HTTP request. Pool should stall.
18536 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618537 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018538 ASSERT_EQ(ERR_IO_PENDING,
18539 http_trans.Start(&http_request, http_callback.callback(),
18540 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118541 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218542
18543 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118544 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218545 std::string response_data;
bnc691fda62016-08-12 00:43:1618546 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218547 EXPECT_EQ("hello world", response_data);
18548
18549 // The SSL socket should automatically be closed, so the HTTP request can
18550 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318551 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118552 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218553
18554 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118555 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618556 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218557 EXPECT_EQ("falafel", response_data);
18558
dcheng48459ac22014-08-26 00:46:4118559 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218560}
18561
18562// Tests that when a SSL connection is established but there's no corresponding
18563// request that needs it, the new socket is closed if the transport socket pool
18564// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118565TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218566 ClientSocketPoolManager::set_max_sockets_per_group(
18567 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18568 ClientSocketPoolManager::set_max_sockets_per_pool(
18569 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18570
18571 // Set up an ssl request.
18572
18573 HttpRequestInfo ssl_request;
18574 ssl_request.method = "GET";
18575 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1018576 ssl_request.traffic_annotation =
18577 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218578
18579 // No data will be sent on the SSL socket.
18580 StaticSocketDataProvider ssl_data;
18581 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18582
18583 SSLSocketDataProvider ssl(ASYNC, OK);
18584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18585
18586 // Set up HTTP request.
18587
18588 HttpRequestInfo http_request;
18589 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318590 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018591 http_request.traffic_annotation =
18592 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218593
18594 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318595 MockWrite(
18596 "GET / HTTP/1.1\r\n"
18597 "Host: www.example.org\r\n"
18598 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218599 };
18600 MockRead http_reads[] = {
18601 MockRead("HTTP/1.1 200 OK\r\n"),
18602 MockRead("Content-Length: 7\r\n\r\n"),
18603 MockRead("falafel"),
18604 MockRead(SYNCHRONOUS, OK),
18605 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118606 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218607 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18608
danakj1fd259a02016-04-16 03:17:0918609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218610
18611 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18612 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918613 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918614 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318615 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218616
18617 // Start the HTTP request. Pool should stall.
18618 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618619 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018620 ASSERT_EQ(ERR_IO_PENDING,
18621 http_trans.Start(&http_request, http_callback.callback(),
18622 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118623 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218624
18625 // The SSL connection will automatically be closed once the connection is
18626 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118627 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218628 std::string response_data;
bnc691fda62016-08-12 00:43:1618629 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218630 EXPECT_EQ("falafel", response_data);
18631
dcheng48459ac22014-08-26 00:46:4118632 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218633}
18634
bncd16676a2016-07-20 16:23:0118635TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918636 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218637 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918638 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218639 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418640
18641 HttpRequestInfo request;
18642 request.method = "POST";
18643 request.url = GURL("http://www.foo.com/");
18644 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018645 request.traffic_annotation =
18646 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418647
danakj1fd259a02016-04-16 03:17:0918648 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618649 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418650 // Send headers successfully, but get an error while sending the body.
18651 MockWrite data_writes[] = {
18652 MockWrite("POST / HTTP/1.1\r\n"
18653 "Host: www.foo.com\r\n"
18654 "Connection: keep-alive\r\n"
18655 "Content-Length: 3\r\n\r\n"),
18656 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18657 };
18658
18659 MockRead data_reads[] = {
18660 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18661 MockRead("hello world"),
18662 MockRead(SYNCHRONOUS, OK),
18663 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118664 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418665 session_deps_.socket_factory->AddSocketDataProvider(&data);
18666
18667 TestCompletionCallback callback;
18668
tfarina42834112016-09-22 13:38:2018669 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118670 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418671
18672 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118673 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418674
bnc691fda62016-08-12 00:43:1618675 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218676 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418677
wezca1070932016-05-26 20:30:5218678 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418679 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18680
18681 std::string response_data;
bnc691fda62016-08-12 00:43:1618682 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118683 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418684 EXPECT_EQ("hello world", response_data);
18685}
18686
18687// This test makes sure the retry logic doesn't trigger when reading an error
18688// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118689TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418690 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418692 MockWrite data_writes[] = {
18693 MockWrite("GET / HTTP/1.1\r\n"
18694 "Host: www.foo.com\r\n"
18695 "Connection: keep-alive\r\n\r\n"),
18696 MockWrite("POST / HTTP/1.1\r\n"
18697 "Host: www.foo.com\r\n"
18698 "Connection: keep-alive\r\n"
18699 "Content-Length: 3\r\n\r\n"),
18700 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18701 };
18702
18703 MockRead data_reads[] = {
18704 MockRead("HTTP/1.1 200 Peachy\r\n"
18705 "Content-Length: 14\r\n\r\n"),
18706 MockRead("first response"),
18707 MockRead("HTTP/1.1 400 Not OK\r\n"
18708 "Content-Length: 15\r\n\r\n"),
18709 MockRead("second response"),
18710 MockRead(SYNCHRONOUS, OK),
18711 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118712 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418713 session_deps_.socket_factory->AddSocketDataProvider(&data);
18714
18715 TestCompletionCallback callback;
18716 HttpRequestInfo request1;
18717 request1.method = "GET";
18718 request1.url = GURL("http://www.foo.com/");
18719 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018720 request1.traffic_annotation =
18721 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418722
bnc87dcefc2017-05-25 12:47:5818723 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918724 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018725 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118726 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418727
18728 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118729 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418730
18731 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218732 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418733
wezca1070932016-05-26 20:30:5218734 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418735 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18736
18737 std::string response_data1;
18738 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118739 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418740 EXPECT_EQ("first response", response_data1);
18741 // Delete the transaction to release the socket back into the socket pool.
18742 trans1.reset();
18743
danakj1fd259a02016-04-16 03:17:0918744 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218745 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918746 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218747 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418748
18749 HttpRequestInfo request2;
18750 request2.method = "POST";
18751 request2.url = GURL("http://www.foo.com/");
18752 request2.upload_data_stream = &upload_data_stream;
18753 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018754 request2.traffic_annotation =
18755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418756
bnc691fda62016-08-12 00:43:1618757 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018758 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118759 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418760
18761 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118762 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418763
bnc691fda62016-08-12 00:43:1618764 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218765 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418766
wezca1070932016-05-26 20:30:5218767 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418768 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18769
18770 std::string response_data2;
bnc691fda62016-08-12 00:43:1618771 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118772 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418773 EXPECT_EQ("second response", response_data2);
18774}
18775
bncd16676a2016-07-20 16:23:0118776TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418777 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918778 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218779 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918780 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218781 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418782
18783 HttpRequestInfo request;
18784 request.method = "POST";
18785 request.url = GURL("http://www.foo.com/");
18786 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018787 request.traffic_annotation =
18788 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418789
danakj1fd259a02016-04-16 03:17:0918790 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618791 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418792 // Send headers successfully, but get an error while sending the body.
18793 MockWrite data_writes[] = {
18794 MockWrite("POST / HTTP/1.1\r\n"
18795 "Host: www.foo.com\r\n"
18796 "Connection: keep-alive\r\n"
18797 "Content-Length: 3\r\n\r\n"
18798 "fo"),
18799 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18800 };
18801
18802 MockRead data_reads[] = {
18803 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18804 MockRead("hello world"),
18805 MockRead(SYNCHRONOUS, OK),
18806 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118807 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418808 session_deps_.socket_factory->AddSocketDataProvider(&data);
18809
18810 TestCompletionCallback callback;
18811
tfarina42834112016-09-22 13:38:2018812 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418814
18815 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118816 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418817
bnc691fda62016-08-12 00:43:1618818 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218819 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418820
wezca1070932016-05-26 20:30:5218821 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418822 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18823
18824 std::string response_data;
bnc691fda62016-08-12 00:43:1618825 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118826 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418827 EXPECT_EQ("hello world", response_data);
18828}
18829
18830// This tests the more common case than the previous test, where headers and
18831// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118832TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718833 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418834
18835 HttpRequestInfo request;
18836 request.method = "POST";
18837 request.url = GURL("http://www.foo.com/");
18838 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018839 request.traffic_annotation =
18840 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418841
danakj1fd259a02016-04-16 03:17:0918842 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618843 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418844 // Send headers successfully, but get an error while sending the body.
18845 MockWrite data_writes[] = {
18846 MockWrite("POST / HTTP/1.1\r\n"
18847 "Host: www.foo.com\r\n"
18848 "Connection: keep-alive\r\n"
18849 "Transfer-Encoding: chunked\r\n\r\n"),
18850 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18851 };
18852
18853 MockRead data_reads[] = {
18854 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18855 MockRead("hello world"),
18856 MockRead(SYNCHRONOUS, OK),
18857 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118858 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418859 session_deps_.socket_factory->AddSocketDataProvider(&data);
18860
18861 TestCompletionCallback callback;
18862
tfarina42834112016-09-22 13:38:2018863 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118864 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418865 // Make sure the headers are sent before adding a chunk. This ensures that
18866 // they can't be merged with the body in a single send. Not currently
18867 // necessary since a chunked body is never merged with headers, but this makes
18868 // the test more future proof.
18869 base::RunLoop().RunUntilIdle();
18870
mmenkecbc2b712014-10-09 20:29:0718871 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418872
18873 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118874 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418875
bnc691fda62016-08-12 00:43:1618876 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218877 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418878
wezca1070932016-05-26 20:30:5218879 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418880 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18881
18882 std::string response_data;
bnc691fda62016-08-12 00:43:1618883 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118884 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418885 EXPECT_EQ("hello world", response_data);
18886}
18887
bncd16676a2016-07-20 16:23:0118888TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918889 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218890 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918891 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218892 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418893
18894 HttpRequestInfo request;
18895 request.method = "POST";
18896 request.url = GURL("http://www.foo.com/");
18897 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018898 request.traffic_annotation =
18899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418900
danakj1fd259a02016-04-16 03:17:0918901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418903
18904 MockWrite data_writes[] = {
18905 MockWrite("POST / HTTP/1.1\r\n"
18906 "Host: www.foo.com\r\n"
18907 "Connection: keep-alive\r\n"
18908 "Content-Length: 3\r\n\r\n"),
18909 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18910 };
18911
18912 MockRead data_reads[] = {
18913 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18914 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18915 MockRead("hello world"),
18916 MockRead(SYNCHRONOUS, OK),
18917 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118918 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418919 session_deps_.socket_factory->AddSocketDataProvider(&data);
18920
18921 TestCompletionCallback callback;
18922
tfarina42834112016-09-22 13:38:2018923 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118924 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418925
18926 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118927 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418928
bnc691fda62016-08-12 00:43:1618929 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218930 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418931
wezca1070932016-05-26 20:30:5218932 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418933 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18934
18935 std::string response_data;
bnc691fda62016-08-12 00:43:1618936 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118937 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418938 EXPECT_EQ("hello world", response_data);
18939}
18940
bncd16676a2016-07-20 16:23:0118941TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918942 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218943 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918944 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218945 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418946
18947 HttpRequestInfo request;
18948 request.method = "POST";
18949 request.url = GURL("http://www.foo.com/");
18950 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018951 request.traffic_annotation =
18952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418953
danakj1fd259a02016-04-16 03:17:0918954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618955 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418956 // Send headers successfully, but get an error while sending the body.
18957 MockWrite data_writes[] = {
18958 MockWrite("POST / HTTP/1.1\r\n"
18959 "Host: www.foo.com\r\n"
18960 "Connection: keep-alive\r\n"
18961 "Content-Length: 3\r\n\r\n"),
18962 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18963 };
18964
18965 MockRead data_reads[] = {
18966 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18967 MockRead("hello world"),
18968 MockRead(SYNCHRONOUS, OK),
18969 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118970 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418971 session_deps_.socket_factory->AddSocketDataProvider(&data);
18972
18973 TestCompletionCallback callback;
18974
tfarina42834112016-09-22 13:38:2018975 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118976 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418977
18978 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118979 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418980}
18981
bncd16676a2016-07-20 16:23:0118982TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418983 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918984 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218985 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918986 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218987 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418988
18989 HttpRequestInfo request;
18990 request.method = "POST";
18991 request.url = GURL("http://www.foo.com/");
18992 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018993 request.traffic_annotation =
18994 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418995
danakj1fd259a02016-04-16 03:17:0918996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618997 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418998 // Send headers successfully, but get an error while sending the body.
18999 MockWrite data_writes[] = {
19000 MockWrite("POST / HTTP/1.1\r\n"
19001 "Host: www.foo.com\r\n"
19002 "Connection: keep-alive\r\n"
19003 "Content-Length: 3\r\n\r\n"),
19004 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19005 };
19006
19007 MockRead data_reads[] = {
19008 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
19009 MockRead("HTTP/1.0 302 Redirect\r\n"),
19010 MockRead("Location: http://somewhere-else.com/\r\n"),
19011 MockRead("Content-Length: 0\r\n\r\n"),
19012 MockRead(SYNCHRONOUS, OK),
19013 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119014 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419015 session_deps_.socket_factory->AddSocketDataProvider(&data);
19016
19017 TestCompletionCallback callback;
19018
tfarina42834112016-09-22 13:38:2019019 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119020 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419021
19022 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119023 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419024}
19025
bncd16676a2016-07-20 16:23:0119026TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0919027 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219028 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919029 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219030 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419031
19032 HttpRequestInfo request;
19033 request.method = "POST";
19034 request.url = GURL("http://www.foo.com/");
19035 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019036 request.traffic_annotation =
19037 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419038
danakj1fd259a02016-04-16 03:17:0919039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419041 // Send headers successfully, but get an error while sending the body.
19042 MockWrite data_writes[] = {
19043 MockWrite("POST / HTTP/1.1\r\n"
19044 "Host: www.foo.com\r\n"
19045 "Connection: keep-alive\r\n"
19046 "Content-Length: 3\r\n\r\n"),
19047 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19048 };
19049
19050 MockRead data_reads[] = {
19051 MockRead("HTTP 0.9 rocks!"),
19052 MockRead(SYNCHRONOUS, OK),
19053 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119054 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419055 session_deps_.socket_factory->AddSocketDataProvider(&data);
19056
19057 TestCompletionCallback callback;
19058
tfarina42834112016-09-22 13:38:2019059 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419061
19062 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119063 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419064}
19065
bncd16676a2016-07-20 16:23:0119066TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0919067 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219068 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919069 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219070 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419071
19072 HttpRequestInfo request;
19073 request.method = "POST";
19074 request.url = GURL("http://www.foo.com/");
19075 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019076 request.traffic_annotation =
19077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419078
danakj1fd259a02016-04-16 03:17:0919079 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619080 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419081 // Send headers successfully, but get an error while sending the body.
19082 MockWrite data_writes[] = {
19083 MockWrite("POST / HTTP/1.1\r\n"
19084 "Host: www.foo.com\r\n"
19085 "Connection: keep-alive\r\n"
19086 "Content-Length: 3\r\n\r\n"),
19087 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19088 };
19089
19090 MockRead data_reads[] = {
19091 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
19092 MockRead(SYNCHRONOUS, OK),
19093 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119094 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419095 session_deps_.socket_factory->AddSocketDataProvider(&data);
19096
19097 TestCompletionCallback callback;
19098
tfarina42834112016-09-22 13:38:2019099 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119100 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419101
19102 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119103 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419104}
19105
Bence Békydca6bd92018-01-30 13:43:0619106#if BUILDFLAG(ENABLE_WEBSOCKETS)
19107
19108namespace {
19109
19110void AddWebSocketHeaders(HttpRequestHeaders* headers) {
19111 headers->SetHeader("Connection", "Upgrade");
19112 headers->SetHeader("Upgrade", "websocket");
19113 headers->SetHeader("Origin", "http://www.example.org");
19114 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0619115}
19116
19117} // namespace
19118
19119TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0119120 for (bool secure : {true, false}) {
19121 MockWrite data_writes[] = {
19122 MockWrite("GET / HTTP/1.1\r\n"
19123 "Host: www.example.org\r\n"
19124 "Connection: Upgrade\r\n"
19125 "Upgrade: websocket\r\n"
19126 "Origin: http://www.example.org\r\n"
19127 "Sec-WebSocket-Version: 13\r\n"
19128 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19129 "Sec-WebSocket-Extensions: permessage-deflate; "
19130 "client_max_window_bits\r\n\r\n")};
19131
19132 MockRead data_reads[] = {
19133 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19134 "Upgrade: websocket\r\n"
19135 "Connection: Upgrade\r\n"
19136 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
19137
Ryan Sleevib8d7ea02018-05-07 20:01:0119138 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0119139 session_deps_.socket_factory->AddSocketDataProvider(&data);
19140 SSLSocketDataProvider ssl(ASYNC, OK);
19141 if (secure)
19142 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0619143
19144 HttpRequestInfo request;
19145 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0119146 request.url =
19147 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19148 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1019149 request.traffic_annotation =
19150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0619151
Bence Béky2fcf4fa2018-04-06 20:06:0119152 TestWebSocketHandshakeStreamCreateHelper
19153 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1519154
Bence Béky2fcf4fa2018-04-06 20:06:0119155 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0619156 HttpNetworkTransaction trans(LOW, session.get());
19157 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0119158 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0619159
19160 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0119161 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19162 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0619163
Bence Béky2fcf4fa2018-04-06 20:06:0119164 const HttpStreamRequest* stream_request = trans.stream_request_.get();
19165 ASSERT_TRUE(stream_request);
19166 EXPECT_EQ(&websocket_handshake_stream_create_helper,
19167 stream_request->websocket_handshake_stream_create_helper());
19168
19169 rv = callback.WaitForResult();
19170 EXPECT_THAT(rv, IsOk());
19171
19172 EXPECT_TRUE(data.AllReadDataConsumed());
19173 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0619174 }
19175}
19176
Adam Rice425cf122015-01-19 06:18:2419177// Verify that proxy headers are not sent to the destination server when
19178// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0119179TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2419180 HttpRequestInfo request;
19181 request.method = "GET";
bncce36dca22015-04-21 22:11:2319182 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019183 request.traffic_annotation =
19184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419185 AddWebSocketHeaders(&request.extra_headers);
19186
19187 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919188 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619189 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919190 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419191
danakj1fd259a02016-04-16 03:17:0919192 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419193
19194 // Since a proxy is configured, try to establish a tunnel.
19195 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1719196 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19197 "Host: www.example.org:443\r\n"
19198 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419199
19200 // After calling trans->RestartWithAuth(), this is the request we should
19201 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1719202 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19203 "Host: www.example.org:443\r\n"
19204 "Proxy-Connection: keep-alive\r\n"
19205 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419206
rsleevidb16bb02015-11-12 23:47:1719207 MockWrite("GET / HTTP/1.1\r\n"
19208 "Host: www.example.org\r\n"
19209 "Connection: Upgrade\r\n"
19210 "Upgrade: websocket\r\n"
19211 "Origin: http://www.example.org\r\n"
19212 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1519213 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19214 "Sec-WebSocket-Extensions: permessage-deflate; "
19215 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419216
19217 // The proxy responds to the connect with a 407, using a persistent
19218 // connection.
19219 MockRead data_reads[] = {
19220 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1519221 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
19222 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
19223 "Content-Length: 0\r\n"
19224 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419225
19226 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19227
Bence Béky8d1c6052018-02-07 12:48:1519228 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19229 "Upgrade: websocket\r\n"
19230 "Connection: Upgrade\r\n"
19231 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419232
Ryan Sleevib8d7ea02018-05-07 20:01:0119233 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419234 session_deps_.socket_factory->AddSocketDataProvider(&data);
19235 SSLSocketDataProvider ssl(ASYNC, OK);
19236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19237
Bence Béky8d1c6052018-02-07 12:48:1519238 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19239
bnc87dcefc2017-05-25 12:47:5819240 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919241 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419242 trans->SetWebSocketHandshakeStreamCreateHelper(
19243 &websocket_stream_create_helper);
19244
19245 {
19246 TestCompletionCallback callback;
19247
tfarina42834112016-09-22 13:38:2019248 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119249 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419250
19251 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119252 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419253 }
19254
19255 const HttpResponseInfo* response = trans->GetResponseInfo();
19256 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219257 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419258 EXPECT_EQ(407, response->headers->response_code());
19259
19260 {
19261 TestCompletionCallback callback;
19262
19263 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
19264 callback.callback());
robpercival214763f2016-07-01 23:27:0119265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419266
19267 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119268 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419269 }
19270
19271 response = trans->GetResponseInfo();
19272 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219273 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419274
19275 EXPECT_EQ(101, response->headers->response_code());
19276
19277 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119278 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419279}
19280
19281// Verify that proxy headers are not sent to the destination server when
19282// establishing a tunnel for an insecure WebSocket connection.
19283// This requires the authentication info to be injected into the auth cache
19284// due to crbug.com/395064
19285// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0119286TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2419287 HttpRequestInfo request;
19288 request.method = "GET";
bncce36dca22015-04-21 22:11:2319289 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019290 request.traffic_annotation =
19291 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419292 AddWebSocketHeaders(&request.extra_headers);
19293
19294 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919295 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619296 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919297 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419298
danakj1fd259a02016-04-16 03:17:0919299 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419300
19301 MockWrite data_writes[] = {
19302 // Try to establish a tunnel for the WebSocket connection, with
19303 // credentials. Because WebSockets have a separate set of socket pools,
19304 // they cannot and will not use the same TCP/IP connection as the
19305 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1519306 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
19307 "Host: www.example.org:80\r\n"
19308 "Proxy-Connection: keep-alive\r\n"
19309 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419310
Bence Béky8d1c6052018-02-07 12:48:1519311 MockWrite("GET / HTTP/1.1\r\n"
19312 "Host: www.example.org\r\n"
19313 "Connection: Upgrade\r\n"
19314 "Upgrade: websocket\r\n"
19315 "Origin: http://www.example.org\r\n"
19316 "Sec-WebSocket-Version: 13\r\n"
19317 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19318 "Sec-WebSocket-Extensions: permessage-deflate; "
19319 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419320
19321 MockRead data_reads[] = {
19322 // HTTP CONNECT with credentials.
19323 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19324
19325 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1519326 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19327 "Upgrade: websocket\r\n"
19328 "Connection: Upgrade\r\n"
19329 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419330
Ryan Sleevib8d7ea02018-05-07 20:01:0119331 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419332 session_deps_.socket_factory->AddSocketDataProvider(&data);
19333
19334 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3319335 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2619336 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
19337 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2419338
Bence Béky8d1c6052018-02-07 12:48:1519339 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19340
bnc87dcefc2017-05-25 12:47:5819341 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919342 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419343 trans->SetWebSocketHandshakeStreamCreateHelper(
19344 &websocket_stream_create_helper);
19345
19346 TestCompletionCallback callback;
19347
tfarina42834112016-09-22 13:38:2019348 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419350
19351 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119352 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419353
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
19358 EXPECT_EQ(101, response->headers->response_code());
19359
19360 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119361 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419362}
19363
Matt Menke1d6093e32019-03-22 17:33:4319364// WebSockets over QUIC is not supported, including over QUIC proxies.
19365TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
19366 for (bool secure : {true, false}) {
19367 SCOPED_TRACE(secure);
19368 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619369 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke1d6093e32019-03-22 17:33:4319370 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
19371 session_deps_.enable_quic = true;
19372
19373 HttpRequestInfo request;
19374 request.url =
19375 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19376 AddWebSocketHeaders(&request.extra_headers);
19377 request.traffic_annotation =
19378 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19379
19380 TestWebSocketHandshakeStreamCreateHelper
19381 websocket_handshake_stream_create_helper;
19382
19383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19384 HttpNetworkTransaction trans(LOW, session.get());
19385 trans.SetWebSocketHandshakeStreamCreateHelper(
19386 &websocket_handshake_stream_create_helper);
19387
19388 TestCompletionCallback callback;
19389 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19390 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19391
19392 rv = callback.WaitForResult();
19393 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
19394 }
19395}
19396
Bence Békydca6bd92018-01-30 13:43:0619397#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
19398
bncd16676a2016-07-20 16:23:0119399TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0919400 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219401 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919402 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219403 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219404
19405 HttpRequestInfo request;
19406 request.method = "POST";
19407 request.url = GURL("http://www.foo.com/");
19408 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019409 request.traffic_annotation =
19410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219411
danakj1fd259a02016-04-16 03:17:0919412 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219414 MockWrite data_writes[] = {
19415 MockWrite("POST / HTTP/1.1\r\n"
19416 "Host: www.foo.com\r\n"
19417 "Connection: keep-alive\r\n"
19418 "Content-Length: 3\r\n\r\n"),
19419 MockWrite("foo"),
19420 };
19421
19422 MockRead data_reads[] = {
19423 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19424 MockRead(SYNCHRONOUS, OK),
19425 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119426 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219427 session_deps_.socket_factory->AddSocketDataProvider(&data);
19428
19429 TestCompletionCallback callback;
19430
19431 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019432 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119433 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219434
19435 std::string response_data;
bnc691fda62016-08-12 00:43:1619436 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219437
Ryan Sleevib8d7ea02018-05-07 20:01:0119438 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19439 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219440}
19441
bncd16676a2016-07-20 16:23:0119442TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919443 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219444 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919445 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219446 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219447
19448 HttpRequestInfo request;
19449 request.method = "POST";
19450 request.url = GURL("http://www.foo.com/");
19451 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019452 request.traffic_annotation =
19453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219454
danakj1fd259a02016-04-16 03:17:0919455 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619456 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219457 MockWrite data_writes[] = {
19458 MockWrite("POST / HTTP/1.1\r\n"
19459 "Host: www.foo.com\r\n"
19460 "Connection: keep-alive\r\n"
19461 "Content-Length: 3\r\n\r\n"),
19462 MockWrite("foo"),
19463 };
19464
19465 MockRead data_reads[] = {
19466 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19467 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19468 MockRead(SYNCHRONOUS, OK),
19469 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119470 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219471 session_deps_.socket_factory->AddSocketDataProvider(&data);
19472
19473 TestCompletionCallback callback;
19474
19475 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019476 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119477 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219478
19479 std::string response_data;
bnc691fda62016-08-12 00:43:1619480 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219481
Ryan Sleevib8d7ea02018-05-07 20:01:0119482 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19483 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219484}
19485
bncd16676a2016-07-20 16:23:0119486TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219487 ChunkedUploadDataStream upload_data_stream(0);
19488
19489 HttpRequestInfo request;
19490 request.method = "POST";
19491 request.url = GURL("http://www.foo.com/");
19492 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019493 request.traffic_annotation =
19494 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219495
danakj1fd259a02016-04-16 03:17:0919496 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619497 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219498 // Send headers successfully, but get an error while sending the body.
19499 MockWrite data_writes[] = {
19500 MockWrite("POST / HTTP/1.1\r\n"
19501 "Host: www.foo.com\r\n"
19502 "Connection: keep-alive\r\n"
19503 "Transfer-Encoding: chunked\r\n\r\n"),
19504 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19505 };
19506
19507 MockRead data_reads[] = {
19508 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19509 MockRead(SYNCHRONOUS, OK),
19510 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119511 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219512 session_deps_.socket_factory->AddSocketDataProvider(&data);
19513
19514 TestCompletionCallback callback;
19515
19516 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019517 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219518
19519 base::RunLoop().RunUntilIdle();
19520 upload_data_stream.AppendData("f", 1, false);
19521
19522 base::RunLoop().RunUntilIdle();
19523 upload_data_stream.AppendData("oo", 2, true);
19524
robpercival214763f2016-07-01 23:27:0119525 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219526
19527 std::string response_data;
bnc691fda62016-08-12 00:43:1619528 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219529
Ryan Sleevib8d7ea02018-05-07 20:01:0119530 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19531 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219532}
19533
eustasc7d27da2017-04-06 10:33:2019534void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19535 const std::string& accept_encoding,
19536 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319537 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019538 bool should_match) {
19539 HttpRequestInfo request;
19540 request.method = "GET";
19541 request.url = GURL("http://www.foo.com/");
19542 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19543 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1019544 request.traffic_annotation =
19545 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019546
19547 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19548 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19549 // Send headers successfully, but get an error while sending the body.
19550 MockWrite data_writes[] = {
19551 MockWrite("GET / HTTP/1.1\r\n"
19552 "Host: www.foo.com\r\n"
19553 "Connection: keep-alive\r\n"
19554 "Accept-Encoding: "),
19555 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19556 };
19557
sky50576f32017-05-01 19:28:0319558 std::string response_code = "200 OK";
19559 std::string extra;
19560 if (!location.empty()) {
19561 response_code = "301 Redirect\r\nLocation: ";
19562 response_code.append(location);
19563 }
19564
eustasc7d27da2017-04-06 10:33:2019565 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319566 MockRead("HTTP/1.0 "),
19567 MockRead(response_code.data()),
19568 MockRead("\r\nContent-Encoding: "),
19569 MockRead(content_encoding.data()),
19570 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019571 MockRead(SYNCHRONOUS, OK),
19572 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119573 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019574 session_deps->socket_factory->AddSocketDataProvider(&data);
19575
19576 TestCompletionCallback callback;
19577
19578 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19579 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19580
19581 rv = callback.WaitForResult();
19582 if (should_match) {
19583 EXPECT_THAT(rv, IsOk());
19584 } else {
19585 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19586 }
19587}
19588
19589TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319590 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019591}
19592
19593TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319594 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19595 true);
eustasc7d27da2017-04-06 10:33:2019596}
19597
19598TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19599 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319600 "", false);
19601}
19602
19603TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19604 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19605 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019606}
19607
xunjieli96f2a402017-06-05 17:24:2719608TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19609 ProxyConfig proxy_config;
19610 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19611 proxy_config.set_pac_mandatory(true);
19612 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619613 session_deps_.proxy_resolution_service.reset(
19614 new ConfiguredProxyResolutionService(
19615 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19616 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919617 std::make_unique<FailingProxyResolverFactory>(), nullptr,
19618 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719619
19620 HttpRequestInfo request;
19621 request.method = "GET";
19622 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019623 request.traffic_annotation =
19624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719625
19626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19627 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19628
19629 TestCompletionCallback callback;
19630
19631 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19633 EXPECT_THAT(callback.WaitForResult(),
19634 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19635}
19636
19637TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19638 ProxyConfig proxy_config;
19639 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19640 proxy_config.set_pac_mandatory(true);
19641 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19642 new MockAsyncProxyResolverFactory(false);
19643 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619644 session_deps_.proxy_resolution_service.reset(
19645 new ConfiguredProxyResolutionService(
19646 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19647 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919648 base::WrapUnique(proxy_resolver_factory), nullptr,
19649 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719650 HttpRequestInfo request;
19651 request.method = "GET";
19652 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019653 request.traffic_annotation =
19654 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719655
19656 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19657 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19658
19659 TestCompletionCallback callback;
19660 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19661 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19662
19663 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19664 ERR_FAILED, &resolver);
19665 EXPECT_THAT(callback.WaitForResult(),
19666 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19667}
19668
19669TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919670 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619671 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919672 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719673 session_deps_.enable_quic = false;
19674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19675
19676 HttpRequestInfo request;
19677 request.method = "GET";
19678 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019679 request.traffic_annotation =
19680 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719681
19682 TestCompletionCallback callback;
19683 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19684 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19685 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19686
19687 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19688}
19689
Douglas Creager3cb042052018-11-06 23:08:5219690//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419691// Reporting tests
19692
19693#if BUILDFLAG(ENABLE_REPORTING)
19694class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19695 protected:
Matt Menkef437a87e2020-10-22 23:22:2419696 HttpNetworkTransactionReportingTest() {
19697 feature_list_.InitAndEnableFeature(
19698 features::kPartitionNelAndReportingByNetworkIsolationKey);
19699 }
19700
Douglas Creager134b52e2018-11-09 18:00:1419701 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619702 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419703 auto test_reporting_context = std::make_unique<TestReportingContext>(
19704 &clock_, &tick_clock_, ReportingPolicy());
19705 test_reporting_context_ = test_reporting_context.get();
19706 session_deps_.reporting_service =
19707 ReportingService::CreateForTesting(std::move(test_reporting_context));
19708 }
19709
19710 TestReportingContext* reporting_context() const {
19711 return test_reporting_context_;
19712 }
19713
19714 void clear_reporting_service() {
19715 session_deps_.reporting_service.reset();
19716 test_reporting_context_ = nullptr;
19717 }
19718
19719 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219720 void RequestPolicy(CertStatus cert_status = 0) {
19721 HttpRequestInfo request;
19722 request.method = "GET";
19723 request.url = GURL(url_);
19724 request.traffic_annotation =
19725 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkef437a87e2020-10-22 23:22:2419726 request.network_isolation_key = kNetworkIsolationKey;
Lily Chenfec60d92019-01-24 01:16:4219727
Lily Chend3930e72019-03-01 19:31:1119728 MockWrite data_writes[] = {
19729 MockWrite("GET / HTTP/1.1\r\n"
19730 "Host: www.example.org\r\n"
19731 "Connection: keep-alive\r\n\r\n"),
19732 };
Douglas Creager134b52e2018-11-09 18:00:1419733 MockRead data_reads[] = {
19734 MockRead("HTTP/1.0 200 OK\r\n"),
19735 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19736 "\"endpoints\": [{\"url\": "
19737 "\"https://www.example.org/upload/\"}]}\r\n"),
19738 MockRead("\r\n"),
19739 MockRead("hello world"),
19740 MockRead(SYNCHRONOUS, OK),
19741 };
Douglas Creager134b52e2018-11-09 18:00:1419742
Lily Chenfec60d92019-01-24 01:16:4219743 StaticSocketDataProvider reads(data_reads, data_writes);
19744 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419745
19746 SSLSocketDataProvider ssl(ASYNC, OK);
19747 if (request.url.SchemeIsCryptographic()) {
19748 ssl.ssl_info.cert =
19749 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19750 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219751 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419752 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19753 }
19754
Douglas Creager134b52e2018-11-09 18:00:1419755 TestCompletionCallback callback;
19756 auto session = CreateSession(&session_deps_);
19757 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19758 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219759 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419760 }
19761
19762 protected:
19763 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419764
19765 private:
Matt Menkef437a87e2020-10-22 23:22:2419766 base::test::ScopedFeatureList feature_list_;
Douglas Creager134b52e2018-11-09 18:00:1419767 TestReportingContext* test_reporting_context_;
19768};
19769
19770TEST_F(HttpNetworkTransactionReportingTest,
19771 DontProcessReportToHeaderNoService) {
Douglas Creager134b52e2018-11-09 18:00:1419772 clear_reporting_service();
19773 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219774 // No crash.
Douglas Creager134b52e2018-11-09 18:00:1419775}
19776
19777TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
Douglas Creager134b52e2018-11-09 18:00:1419778 url_ = "http://www.example.org/";
19779 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219780 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419781}
19782
19783TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19784 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419785 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019786 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419787 reporting_context()->cache()->GetEndpointForTesting(
Lily Chenad5dd0802020-03-10 21:58:0919788 ReportingEndpointGroupKey(
Matt Menkef437a87e2020-10-22 23:22:2419789 kNetworkIsolationKey,
Lily Chenad5dd0802020-03-10 21:58:0919790 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
Lily Chenefb6fcf2019-04-19 04:17:5419791 GURL("https://www.example.org/upload/"));
19792 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419793}
19794
19795TEST_F(HttpNetworkTransactionReportingTest,
19796 DontProcessReportToHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4219797 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19798 RequestPolicy(cert_status);
Lily Chen9364a4c2020-06-25 16:07:5219799 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419800}
19801#endif // BUILDFLAG(ENABLE_REPORTING)
19802
19803//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219804// Network Error Logging tests
19805
19806#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219807namespace {
19808
19809const char kUserAgent[] = "Mozilla/1.0";
19810const char kReferrer[] = "https://www.referrer.org/";
19811
19812} // namespace
19813
Douglas Creager3cb042052018-11-06 23:08:5219814class HttpNetworkTransactionNetworkErrorLoggingTest
19815 : public HttpNetworkTransactionTest {
19816 protected:
19817 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619818 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219819 auto network_error_logging_service =
19820 std::make_unique<TestNetworkErrorLoggingService>();
19821 test_network_error_logging_service_ = network_error_logging_service.get();
19822 session_deps_.network_error_logging_service =
19823 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219824
19825 extra_headers_.SetHeader("User-Agent", kUserAgent);
19826 extra_headers_.SetHeader("Referer", kReferrer);
19827
19828 request_.method = "GET";
19829 request_.url = GURL(url_);
Matt Menkef437a87e2020-10-22 23:22:2419830 request_.network_isolation_key = kNetworkIsolationKey;
Lily Chenfec60d92019-01-24 01:16:4219831 request_.extra_headers = extra_headers_;
19832 request_.reporting_upload_depth = reporting_upload_depth_;
19833 request_.traffic_annotation =
19834 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219835 }
19836
19837 TestNetworkErrorLoggingService* network_error_logging_service() const {
19838 return test_network_error_logging_service_;
19839 }
19840
19841 void clear_network_error_logging_service() {
19842 session_deps_.network_error_logging_service.reset();
19843 test_network_error_logging_service_ = nullptr;
19844 }
19845
19846 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219847 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619848 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319849 MockWrite data_writes[] = {
19850 MockWrite("GET / HTTP/1.1\r\n"
19851 "Host: www.example.org\r\n"
19852 "Connection: keep-alive\r\n"),
19853 MockWrite(ASYNC, extra_header_string.data(),
19854 extra_header_string.size()),
19855 };
Lily Chend3930e72019-03-01 19:31:1119856 MockRead data_reads[] = {
19857 MockRead("HTTP/1.0 200 OK\r\n"),
19858 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19859 MockRead("\r\n"),
19860 MockRead("hello world"),
19861 MockRead(SYNCHRONOUS, OK),
19862 };
Douglas Creager3cb042052018-11-06 23:08:5219863
Lily Chenfec60d92019-01-24 01:16:4219864 StaticSocketDataProvider reads(data_reads, data_writes);
19865 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219866
19867 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219868 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219869 ssl.ssl_info.cert =
19870 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19871 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219872 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219873 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19874 }
19875
Douglas Creager3cb042052018-11-06 23:08:5219876 TestCompletionCallback callback;
19877 auto session = CreateSession(&session_deps_);
19878 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219879 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19880 EXPECT_THAT(callback.GetResult(rv), IsOk());
19881
19882 std::string response_data;
19883 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19884 EXPECT_EQ("hello world", response_data);
19885 }
19886
19887 void CheckReport(size_t index,
19888 int status_code,
19889 int error_type,
19890 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19891 ASSERT_LT(index, network_error_logging_service()->errors().size());
19892
19893 const NetworkErrorLoggingService::RequestDetails& error =
19894 network_error_logging_service()->errors()[index];
19895 EXPECT_EQ(url_, error.uri);
Matt Menkef437a87e2020-10-22 23:22:2419896 EXPECT_EQ(kNetworkIsolationKey, error.network_isolation_key);
Lily Chenfec60d92019-01-24 01:16:4219897 EXPECT_EQ(kReferrer, error.referrer);
19898 EXPECT_EQ(kUserAgent, error.user_agent);
19899 EXPECT_EQ(server_ip, error.server_ip);
19900 EXPECT_EQ("http/1.1", error.protocol);
19901 EXPECT_EQ("GET", error.method);
19902 EXPECT_EQ(status_code, error.status_code);
19903 EXPECT_EQ(error_type, error.type);
19904 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219905 }
19906
19907 protected:
19908 std::string url_ = "https://www.example.org/";
19909 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219910 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619911 HttpRequestHeaders extra_headers_;
19912 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219913
19914 private:
19915 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19916};
19917
19918TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19919 DontProcessNelHeaderNoService) {
Douglas Creager3cb042052018-11-06 23:08:5219920 clear_network_error_logging_service();
19921 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4919922 // No crash.
Douglas Creager3cb042052018-11-06 23:08:5219923}
19924
19925TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19926 DontProcessNelHeaderHttp) {
Douglas Creager3cb042052018-11-06 23:08:5219927 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219928 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219929 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4919930 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5219931}
19932
Lily Chen90ae93cc2019-02-14 01:15:3919933// Don't set NEL policies received on a proxied connection.
19934TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19935 DontProcessNelHeaderProxy) {
19936 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619937 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3919938 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1419939 RecordingBoundTestNetLog log;
Lily Chen90ae93cc2019-02-14 01:15:3919940 session_deps_.net_log = log.bound().net_log();
19941 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19942
19943 HttpRequestInfo request;
19944 request.method = "GET";
19945 request.url = GURL("https://www.example.org/");
19946 request.traffic_annotation =
19947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19948
19949 // Since we have proxy, should try to establish tunnel.
19950 MockWrite data_writes1[] = {
19951 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19952 "Host: www.example.org:443\r\n"
19953 "Proxy-Connection: keep-alive\r\n\r\n"),
19954
19955 MockWrite("GET / HTTP/1.1\r\n"
19956 "Host: www.example.org\r\n"
19957 "Connection: keep-alive\r\n\r\n"),
19958 };
19959
19960 MockRead data_reads1[] = {
19961 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19962
19963 MockRead("HTTP/1.1 200 OK\r\n"),
19964 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19965 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19966 MockRead("Content-Length: 100\r\n\r\n"),
19967 MockRead(SYNCHRONOUS, OK),
19968 };
19969
19970 StaticSocketDataProvider data1(data_reads1, data_writes1);
19971 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19972 SSLSocketDataProvider ssl(ASYNC, OK);
19973 ssl.ssl_info.cert =
19974 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19975 ASSERT_TRUE(ssl.ssl_info.cert);
19976 ssl.ssl_info.cert_status = 0;
19977 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19978
19979 TestCompletionCallback callback1;
19980 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19981
19982 int rv = trans.Start(&request, callback1.callback(), log.bound());
19983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19984
19985 rv = callback1.WaitForResult();
19986 EXPECT_THAT(rv, IsOk());
19987
19988 const HttpResponseInfo* response = trans.GetResponseInfo();
19989 ASSERT_TRUE(response);
19990 EXPECT_EQ(200, response->headers->response_code());
19991 EXPECT_TRUE(response->was_fetched_via_proxy);
19992
19993 // No NEL header was set.
19994 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19995}
19996
Douglas Creager3cb042052018-11-06 23:08:5219997TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19998 RequestPolicy();
19999 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
20000 const auto& header = network_error_logging_service()->headers()[0];
Matt Menkef437a87e2020-10-22 23:22:2420001 EXPECT_EQ(kNetworkIsolationKey, header.network_isolation_key);
Douglas Creager3cb042052018-11-06 23:08:5220002 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
20003 header.origin);
20004 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
20005 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
20006}
20007
20008TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20009 DontProcessNelHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4220010 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
20011 RequestPolicy(cert_status);
Lily Chena9e9d6cb2020-06-25 17:34:4920012 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5220013}
Douglas Creageref5eecdc2018-11-09 20:50:3620014
Lily Chenfec60d92019-01-24 01:16:4220015TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3620016 RequestPolicy();
20017 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220018 CheckReport(0 /* index */, 200 /* status_code */, OK);
20019}
20020
20021TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20022 CreateReportErrorAfterStart) {
20023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20024 auto trans =
20025 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20026
20027 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
20028 StaticSocketDataProvider data;
20029 data.set_connect_data(mock_connect);
20030 session_deps_.socket_factory->AddSocketDataProvider(&data);
20031
20032 TestCompletionCallback callback;
20033
20034 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20035 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20036
20037 trans.reset();
20038
20039 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20040 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20041 IPAddress() /* server_ip */);
20042}
20043
20044// Same as above except the error is ASYNC
20045TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20046 CreateReportErrorAfterStartAsync) {
20047 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20048 auto trans =
20049 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20050
20051 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
20052 StaticSocketDataProvider data;
20053 data.set_connect_data(mock_connect);
20054 session_deps_.socket_factory->AddSocketDataProvider(&data);
20055
20056 TestCompletionCallback callback;
20057
20058 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20059 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20060
20061 trans.reset();
20062
20063 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20064 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20065 IPAddress() /* server_ip */);
20066}
20067
20068TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20069 CreateReportReadBodyError) {
20070 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320071 MockWrite data_writes[] = {
20072 MockWrite("GET / HTTP/1.1\r\n"
20073 "Host: www.example.org\r\n"
20074 "Connection: keep-alive\r\n"),
20075 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20076 };
Lily Chend3930e72019-03-01 19:31:1120077 MockRead data_reads[] = {
20078 MockRead("HTTP/1.0 200 OK\r\n"),
20079 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20080 MockRead("hello world"),
20081 MockRead(SYNCHRONOUS, OK),
20082 };
Lily Chenfec60d92019-01-24 01:16:4220083
20084 StaticSocketDataProvider reads(data_reads, data_writes);
20085 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20086
20087 SSLSocketDataProvider ssl(ASYNC, OK);
20088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20089
20090 // Log start time
20091 base::TimeTicks start_time = base::TimeTicks::Now();
20092
20093 TestCompletionCallback callback;
20094 auto session = CreateSession(&session_deps_);
20095 auto trans =
20096 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20097 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20098 EXPECT_THAT(callback.GetResult(rv), IsOk());
20099
20100 const HttpResponseInfo* response = trans->GetResponseInfo();
20101 ASSERT_TRUE(response);
20102
20103 EXPECT_TRUE(response->headers);
20104 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20105
20106 std::string response_data;
20107 rv = ReadTransaction(trans.get(), &response_data);
20108 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20109
20110 trans.reset();
20111
20112 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20113
20114 CheckReport(0 /* index */, 200 /* status_code */,
20115 ERR_CONTENT_LENGTH_MISMATCH);
20116 const NetworkErrorLoggingService::RequestDetails& error =
20117 network_error_logging_service()->errors()[0];
20118 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20119}
20120
20121// Same as above except the final read is ASYNC.
20122TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20123 CreateReportReadBodyErrorAsync) {
20124 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320125 MockWrite data_writes[] = {
20126 MockWrite("GET / HTTP/1.1\r\n"
20127 "Host: www.example.org\r\n"
20128 "Connection: keep-alive\r\n"),
20129 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20130 };
Lily Chend3930e72019-03-01 19:31:1120131 MockRead data_reads[] = {
20132 MockRead("HTTP/1.0 200 OK\r\n"),
20133 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20134 MockRead("hello world"),
20135 MockRead(ASYNC, OK),
20136 };
Lily Chenfec60d92019-01-24 01:16:4220137
20138 StaticSocketDataProvider reads(data_reads, data_writes);
20139 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20140
20141 SSLSocketDataProvider ssl(ASYNC, OK);
20142 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20143
20144 // Log start time
20145 base::TimeTicks start_time = base::TimeTicks::Now();
20146
20147 TestCompletionCallback callback;
20148 auto session = CreateSession(&session_deps_);
20149 auto trans =
20150 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20151 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20152 EXPECT_THAT(callback.GetResult(rv), IsOk());
20153
20154 const HttpResponseInfo* response = trans->GetResponseInfo();
20155 ASSERT_TRUE(response);
20156
20157 EXPECT_TRUE(response->headers);
20158 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20159
20160 std::string response_data;
20161 rv = ReadTransaction(trans.get(), &response_data);
20162 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20163
20164 trans.reset();
20165
20166 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20167
20168 CheckReport(0 /* index */, 200 /* status_code */,
20169 ERR_CONTENT_LENGTH_MISMATCH);
20170 const NetworkErrorLoggingService::RequestDetails& error =
20171 network_error_logging_service()->errors()[0];
20172 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20173}
20174
20175TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20176 CreateReportRestartWithAuth) {
20177 std::string extra_header_string = extra_headers_.ToString();
20178 static const base::TimeDelta kSleepDuration =
20179 base::TimeDelta::FromMilliseconds(10);
20180
20181 MockWrite data_writes1[] = {
20182 MockWrite("GET / HTTP/1.1\r\n"
20183 "Host: www.example.org\r\n"
20184 "Connection: keep-alive\r\n"),
20185 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20186 };
20187
20188 MockRead data_reads1[] = {
20189 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20190 // Give a couple authenticate options (only the middle one is actually
20191 // supported).
20192 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20193 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20194 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20196 // Large content-length -- won't matter, as connection will be reset.
20197 MockRead("Content-Length: 10000\r\n\r\n"),
20198 MockRead(SYNCHRONOUS, ERR_FAILED),
20199 };
20200
20201 // After calling trans->RestartWithAuth(), this is the request we should
20202 // be issuing -- the final header line contains the credentials.
20203 MockWrite data_writes2[] = {
20204 MockWrite("GET / HTTP/1.1\r\n"
20205 "Host: www.example.org\r\n"
20206 "Connection: keep-alive\r\n"
20207 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20208 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20209 };
20210
20211 // Lastly, the server responds with the actual content.
20212 MockRead data_reads2[] = {
20213 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20214 MockRead("hello world"),
20215 MockRead(SYNCHRONOUS, OK),
20216 };
20217
20218 StaticSocketDataProvider data1(data_reads1, data_writes1);
20219 StaticSocketDataProvider data2(data_reads2, data_writes2);
20220 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20221 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20222
20223 SSLSocketDataProvider ssl1(ASYNC, OK);
20224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20225 SSLSocketDataProvider ssl2(ASYNC, OK);
20226 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20227
20228 base::TimeTicks start_time = base::TimeTicks::Now();
20229 base::TimeTicks restart_time;
20230
20231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20232 auto trans =
20233 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20234
20235 TestCompletionCallback callback1;
20236
20237 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20238 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20239
20240 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20241
20242 TestCompletionCallback callback2;
20243
20244 // Wait 10 ms then restart with auth
20245 FastForwardBy(kSleepDuration);
20246 restart_time = base::TimeTicks::Now();
20247 rv =
20248 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20249 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20250
20251 std::string response_data;
20252 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20253 EXPECT_EQ("hello world", response_data);
20254
20255 trans.reset();
20256
20257 // One 401 report for the auth challenge, then a 200 report for the successful
20258 // retry. Note that we don't report the error draining the body, as the first
20259 // request already generated a report for the auth challenge.
20260 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20261
20262 // Check error report contents
20263 CheckReport(0 /* index */, 401 /* status_code */, OK);
20264 CheckReport(1 /* index */, 200 /* status_code */, OK);
20265
20266 const NetworkErrorLoggingService::RequestDetails& error1 =
20267 network_error_logging_service()->errors()[0];
20268 const NetworkErrorLoggingService::RequestDetails& error2 =
20269 network_error_logging_service()->errors()[1];
20270
20271 // Sanity-check elapsed time values
20272 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20273 // Check that the start time is refreshed when restarting with auth.
20274 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20275}
20276
20277// Same as above, except draining the body before restarting fails
20278// asynchronously.
20279TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20280 CreateReportRestartWithAuthAsync) {
20281 std::string extra_header_string = extra_headers_.ToString();
20282 static const base::TimeDelta kSleepDuration =
20283 base::TimeDelta::FromMilliseconds(10);
20284
20285 MockWrite data_writes1[] = {
20286 MockWrite("GET / HTTP/1.1\r\n"
20287 "Host: www.example.org\r\n"
20288 "Connection: keep-alive\r\n"),
20289 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20290 };
20291
20292 MockRead data_reads1[] = {
20293 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20294 // Give a couple authenticate options (only the middle one is actually
20295 // supported).
20296 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20297 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20298 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20300 // Large content-length -- won't matter, as connection will be reset.
20301 MockRead("Content-Length: 10000\r\n\r\n"),
20302 MockRead(ASYNC, ERR_FAILED),
20303 };
20304
20305 // After calling trans->RestartWithAuth(), this is the request we should
20306 // be issuing -- the final header line contains the credentials.
20307 MockWrite data_writes2[] = {
20308 MockWrite("GET / HTTP/1.1\r\n"
20309 "Host: www.example.org\r\n"
20310 "Connection: keep-alive\r\n"
20311 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20312 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20313 };
20314
20315 // Lastly, the server responds with the actual content.
20316 MockRead data_reads2[] = {
20317 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20318 MockRead("hello world"),
20319 MockRead(SYNCHRONOUS, OK),
20320 };
20321
20322 StaticSocketDataProvider data1(data_reads1, data_writes1);
20323 StaticSocketDataProvider data2(data_reads2, data_writes2);
20324 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20325 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20326
20327 SSLSocketDataProvider ssl1(ASYNC, OK);
20328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20329 SSLSocketDataProvider ssl2(ASYNC, OK);
20330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20331
20332 base::TimeTicks start_time = base::TimeTicks::Now();
20333 base::TimeTicks restart_time;
20334
20335 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20336 auto trans =
20337 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20338
20339 TestCompletionCallback callback1;
20340
20341 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20342 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20343
20344 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20345
20346 TestCompletionCallback callback2;
20347
20348 // Wait 10 ms then restart with auth
20349 FastForwardBy(kSleepDuration);
20350 restart_time = base::TimeTicks::Now();
20351 rv =
20352 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20353 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20354
20355 std::string response_data;
20356 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20357 EXPECT_EQ("hello world", response_data);
20358
20359 trans.reset();
20360
20361 // One 401 report for the auth challenge, then a 200 report for the successful
20362 // retry. Note that we don't report the error draining the body, as the first
20363 // request already generated a report for the auth challenge.
20364 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20365
20366 // Check error report contents
20367 CheckReport(0 /* index */, 401 /* status_code */, OK);
20368 CheckReport(1 /* index */, 200 /* status_code */, OK);
20369
20370 const NetworkErrorLoggingService::RequestDetails& error1 =
20371 network_error_logging_service()->errors()[0];
20372 const NetworkErrorLoggingService::RequestDetails& error2 =
20373 network_error_logging_service()->errors()[1];
20374
20375 // Sanity-check elapsed time values
20376 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20377 // Check that the start time is refreshed when restarting with auth.
20378 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20379}
20380
20381TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20382 CreateReportRetryKeepAliveConnectionReset) {
20383 std::string extra_header_string = extra_headers_.ToString();
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 MockWrite("GET / HTTP/1.1\r\n"
20390 "Host: www.example.org\r\n"
20391 "Connection: keep-alive\r\n"),
20392 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20393 };
20394
20395 MockRead data_reads1[] = {
20396 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20397 MockRead("hello"),
20398 // Connection is reset
20399 MockRead(ASYNC, ERR_CONNECTION_RESET),
20400 };
20401
20402 // Successful retry
20403 MockRead data_reads2[] = {
20404 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20405 MockRead("world"),
20406 MockRead(ASYNC, OK),
20407 };
20408
20409 StaticSocketDataProvider data1(data_reads1, data_writes1);
20410 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20411 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20412 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20413
20414 SSLSocketDataProvider ssl1(ASYNC, OK);
20415 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20416 SSLSocketDataProvider ssl2(ASYNC, OK);
20417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20418
20419 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20420 auto trans1 =
20421 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20422
20423 TestCompletionCallback callback1;
20424
20425 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20426 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20427
20428 std::string response_data;
20429 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20430 EXPECT_EQ("hello", response_data);
20431
20432 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20433
20434 auto trans2 =
20435 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20436
20437 TestCompletionCallback callback2;
20438
20439 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20440 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20441
20442 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20443 EXPECT_EQ("world", response_data);
20444
20445 trans1.reset();
20446 trans2.reset();
20447
20448 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20449 // the second request, then an OK report from the successful retry.
20450 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20451
20452 // Check error report contents
20453 CheckReport(0 /* index */, 200 /* status_code */, OK);
20454 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20455 CheckReport(2 /* index */, 200 /* status_code */, OK);
20456}
20457
20458TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20459 CreateReportRetryKeepAlive408) {
20460 std::string extra_header_string = extra_headers_.ToString();
20461 MockWrite data_writes1[] = {
20462 MockWrite("GET / HTTP/1.1\r\n"
20463 "Host: www.example.org\r\n"
20464 "Connection: keep-alive\r\n"),
20465 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20466 MockWrite("GET / HTTP/1.1\r\n"
20467 "Host: www.example.org\r\n"
20468 "Connection: keep-alive\r\n"),
20469 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20470 };
20471
20472 MockRead data_reads1[] = {
20473 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20474 MockRead("hello"),
20475 // 408 Request Timeout
20476 MockRead(SYNCHRONOUS,
20477 "HTTP/1.1 408 Request Timeout\r\n"
20478 "Connection: Keep-Alive\r\n"
20479 "Content-Length: 6\r\n\r\n"
20480 "Pickle"),
20481 };
20482
20483 // Successful retry
20484 MockRead data_reads2[] = {
20485 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20486 MockRead("world"),
20487 MockRead(ASYNC, OK),
20488 };
20489
20490 StaticSocketDataProvider data1(data_reads1, data_writes1);
20491 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20492 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20493 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20494
20495 SSLSocketDataProvider ssl1(ASYNC, OK);
20496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20497 SSLSocketDataProvider ssl2(ASYNC, OK);
20498 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20499
20500 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20501 auto trans1 =
20502 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20503
20504 TestCompletionCallback callback1;
20505
20506 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20507 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20508
20509 std::string response_data;
20510 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20511 EXPECT_EQ("hello", response_data);
20512
20513 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20514
20515 auto trans2 =
20516 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20517
20518 TestCompletionCallback callback2;
20519
20520 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20521 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20522
20523 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20524 EXPECT_EQ("world", response_data);
20525
20526 trans1.reset();
20527 trans2.reset();
20528
20529 // One 200 report from first request, then a 408 report from
20530 // the second request, then a 200 report from the successful retry.
20531 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20532
20533 // Check error report contents
20534 CheckReport(0 /* index */, 200 /* status_code */, OK);
20535 CheckReport(1 /* index */, 408 /* status_code */, OK);
20536 CheckReport(2 /* index */, 200 /* status_code */, OK);
20537}
20538
20539TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20540 CreateReportRetry421WithoutConnectionPooling) {
20541 // Two hosts resolve to the same IP address.
20542 const std::string ip_addr = "1.2.3.4";
20543 IPAddress ip;
20544 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20545 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20546
20547 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20548 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20549 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20550
20551 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20552
20553 // Two requests on the first connection.
20554 spdy::SpdySerializedFrame req1(
20555 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20556 spdy_util_.UpdateWithStreamDestruction(1);
20557 spdy::SpdySerializedFrame req2(
20558 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20559 spdy::SpdySerializedFrame rst(
20560 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20561 MockWrite writes1[] = {
20562 CreateMockWrite(req1, 0),
20563 CreateMockWrite(req2, 3),
20564 CreateMockWrite(rst, 6),
20565 };
20566
20567 // The first one succeeds, the second gets error 421 Misdirected Request.
20568 spdy::SpdySerializedFrame resp1(
20569 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20570 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky4c325e52020-10-22 20:48:0120571 spdy::Http2HeaderBlock response_headers;
Lily Chenfec60d92019-01-24 01:16:4220572 response_headers[spdy::kHttp2StatusHeader] = "421";
20573 spdy::SpdySerializedFrame resp2(
20574 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20575 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20576 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20577
20578 MockConnect connect1(ASYNC, OK, peer_addr);
20579 SequencedSocketData data1(connect1, reads1, writes1);
20580 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20581
20582 AddSSLSocketData();
20583
20584 // Retry the second request on a second connection.
20585 SpdyTestUtil spdy_util2;
20586 spdy::SpdySerializedFrame req3(
20587 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20588 MockWrite writes2[] = {
20589 CreateMockWrite(req3, 0),
20590 };
20591
20592 spdy::SpdySerializedFrame resp3(
20593 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20594 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20595 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20596 MockRead(ASYNC, 0, 3)};
20597
20598 MockConnect connect2(ASYNC, OK, peer_addr);
20599 SequencedSocketData data2(connect2, reads2, writes2);
20600 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20601
20602 AddSSLSocketData();
20603
20604 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320605 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320606 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20607 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320608 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220609
20610 HttpRequestInfo request1;
20611 request1.method = "GET";
20612 request1.url = GURL("https://www.example.org/");
20613 request1.load_flags = 0;
20614 request1.traffic_annotation =
20615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20616 auto trans1 =
20617 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20618
Eric Orthf4db66a2019-02-19 21:35:3320619 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220620 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20621 EXPECT_THAT(callback.GetResult(rv), IsOk());
20622
20623 const HttpResponseInfo* response = trans1->GetResponseInfo();
20624 ASSERT_TRUE(response);
20625 ASSERT_TRUE(response->headers);
20626 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20627 EXPECT_TRUE(response->was_fetched_via_spdy);
20628 EXPECT_TRUE(response->was_alpn_negotiated);
20629 std::string response_data;
20630 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20631 EXPECT_EQ("hello!", response_data);
20632
20633 trans1.reset();
20634
20635 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20636
20637 HttpRequestInfo request2;
20638 request2.method = "GET";
20639 request2.url = GURL("https://mail.example.org/");
20640 request2.load_flags = 0;
20641 request2.traffic_annotation =
20642 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20643 auto trans2 =
20644 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20645
Matt Muellerd9342e3a2019-11-26 01:41:1420646 RecordingBoundTestNetLog log;
Lily Chenfec60d92019-01-24 01:16:4220647 rv = trans2->Start(&request2, callback.callback(), log.bound());
20648 EXPECT_THAT(callback.GetResult(rv), IsOk());
20649
20650 response = trans2->GetResponseInfo();
20651 ASSERT_TRUE(response);
20652 ASSERT_TRUE(response->headers);
20653 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20654 EXPECT_TRUE(response->was_fetched_via_spdy);
20655 EXPECT_TRUE(response->was_alpn_negotiated);
20656 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20657 EXPECT_EQ("hello!", response_data);
20658
20659 trans2.reset();
20660
20661 // One 200 report from the first request, then a 421 report from the
20662 // second request, then a 200 report from the successful retry.
20663 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20664
20665 // Check error report contents
20666 const NetworkErrorLoggingService::RequestDetails& error1 =
20667 network_error_logging_service()->errors()[0];
20668 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20669 EXPECT_TRUE(error1.referrer.is_empty());
20670 EXPECT_EQ("", error1.user_agent);
20671 EXPECT_EQ(ip, error1.server_ip);
20672 EXPECT_EQ("h2", error1.protocol);
20673 EXPECT_EQ("GET", error1.method);
20674 EXPECT_EQ(200, error1.status_code);
20675 EXPECT_EQ(OK, error1.type);
20676 EXPECT_EQ(0, error1.reporting_upload_depth);
20677
20678 const NetworkErrorLoggingService::RequestDetails& error2 =
20679 network_error_logging_service()->errors()[1];
20680 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20681 EXPECT_TRUE(error2.referrer.is_empty());
20682 EXPECT_EQ("", error2.user_agent);
20683 EXPECT_EQ(ip, error2.server_ip);
20684 EXPECT_EQ("h2", error2.protocol);
20685 EXPECT_EQ("GET", error2.method);
20686 EXPECT_EQ(421, error2.status_code);
20687 EXPECT_EQ(OK, error2.type);
20688 EXPECT_EQ(0, error2.reporting_upload_depth);
20689
20690 const NetworkErrorLoggingService::RequestDetails& error3 =
20691 network_error_logging_service()->errors()[2];
20692 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20693 EXPECT_TRUE(error3.referrer.is_empty());
20694 EXPECT_EQ("", error3.user_agent);
20695 EXPECT_EQ(ip, error3.server_ip);
20696 EXPECT_EQ("h2", error3.protocol);
20697 EXPECT_EQ("GET", error3.method);
20698 EXPECT_EQ(200, error3.status_code);
20699 EXPECT_EQ(OK, error3.type);
20700 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620701}
20702
Lily Chend3930e72019-03-01 19:31:1120703TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20704 CreateReportCancelAfterStart) {
20705 StaticSocketDataProvider data;
20706 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20707 session_deps_.socket_factory->AddSocketDataProvider(&data);
20708
20709 TestCompletionCallback callback;
20710 auto session = CreateSession(&session_deps_);
20711 auto trans =
20712 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20713 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20714 EXPECT_EQ(rv, ERR_IO_PENDING);
20715
20716 // Cancel after start.
20717 trans.reset();
20718
20719 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20720 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20721 IPAddress() /* server_ip */);
20722}
20723
20724TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20725 CreateReportCancelBeforeReadingBody) {
20726 std::string extra_header_string = extra_headers_.ToString();
20727 MockWrite data_writes[] = {
20728 MockWrite("GET / HTTP/1.1\r\n"
20729 "Host: www.example.org\r\n"
20730 "Connection: keep-alive\r\n"),
20731 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20732 };
20733 MockRead data_reads[] = {
20734 MockRead("HTTP/1.0 200 OK\r\n"),
20735 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20736 };
20737
20738 StaticSocketDataProvider data(data_reads, data_writes);
20739 session_deps_.socket_factory->AddSocketDataProvider(&data);
20740
20741 SSLSocketDataProvider ssl(ASYNC, OK);
20742 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20743
20744 TestCompletionCallback callback;
20745 auto session = CreateSession(&session_deps_);
20746 auto trans =
20747 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20748 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20749 EXPECT_THAT(callback.GetResult(rv), IsOk());
20750
20751 const HttpResponseInfo* response = trans->GetResponseInfo();
20752 ASSERT_TRUE(response);
20753
20754 EXPECT_TRUE(response->headers);
20755 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20756
20757 // Cancel before reading the body.
20758 trans.reset();
20759
20760 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20761 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20762}
20763
Lily Chen00196ab62018-12-04 19:52:2920764TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
Lily Chen00196ab62018-12-04 19:52:2920765 RequestPolicy();
20766 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20767 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20768
20769 // Make HTTP request
20770 std::string extra_header_string = extra_headers_.ToString();
20771 MockRead data_reads[] = {
20772 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20773 MockRead("hello world"),
20774 MockRead(SYNCHRONOUS, OK),
20775 };
20776 MockWrite data_writes[] = {
20777 MockWrite("GET / HTTP/1.1\r\n"
20778 "Host: www.example.org\r\n"
20779 "Connection: keep-alive\r\n"),
20780 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20781 };
20782
Lily Chend3930e72019-03-01 19:31:1120783 StaticSocketDataProvider data(data_reads, data_writes);
20784 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920785
Lily Chenfec60d92019-01-24 01:16:4220786 // Insecure url
20787 url_ = "http://www.example.org/";
20788 request_.url = GURL(url_);
20789
Lily Chen00196ab62018-12-04 19:52:2920790 TestCompletionCallback callback;
20791 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220792 auto trans =
20793 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20794 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20795 EXPECT_THAT(callback.GetResult(rv), IsOk());
20796
20797 std::string response_data;
20798 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20799 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920800
20801 // Insecure request does not generate a report
Lily Chen00196ab62018-12-04 19:52:2920802 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20803}
20804
20805TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20806 DontCreateReportHttpError) {
Lily Chen00196ab62018-12-04 19:52:2920807 RequestPolicy();
20808 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20809 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20810
20811 // Make HTTP request that fails
20812 MockRead data_reads[] = {
20813 MockRead("hello world"),
20814 MockRead(SYNCHRONOUS, OK),
20815 };
20816
20817 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20818 session_deps_.socket_factory->AddSocketDataProvider(&data);
20819
Lily Chenfec60d92019-01-24 01:16:4220820 url_ = "http://www.originwithoutpolicy.com:2000/";
20821 request_.url = GURL(url_);
20822
Lily Chen00196ab62018-12-04 19:52:2920823 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20824
Lily Chen00196ab62018-12-04 19:52:2920825 auto trans =
20826 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920827 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220828 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920829 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20830
20831 // Insecure request does not generate a report, regardless of existence of a
20832 // policy for the origin.
Lily Chen00196ab62018-12-04 19:52:2920833 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20834}
20835
Lily Chen90ae93cc2019-02-14 01:15:3920836// Don't report on proxy auth challenges, don't report if connecting through a
20837// proxy.
20838TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20839 HttpRequestInfo request;
20840 request.method = "GET";
20841 request.url = GURL("https://www.example.org/");
20842 request.traffic_annotation =
20843 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20844
20845 // Configure against proxy server "myproxy:70".
20846 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620847 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920848 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20850
20851 // Since we have proxy, should try to establish tunnel.
20852 MockWrite data_writes1[] = {
20853 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20854 "Host: www.example.org:443\r\n"
20855 "Proxy-Connection: keep-alive\r\n\r\n"),
20856 };
20857
20858 // The proxy responds to the connect with a 407, using a non-persistent
20859 // connection.
20860 MockRead data_reads1[] = {
20861 // No credentials.
20862 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20863 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20864 MockRead("Proxy-Connection: close\r\n\r\n"),
20865 };
20866
20867 MockWrite data_writes2[] = {
20868 // After calling trans->RestartWithAuth(), this is the request we should
20869 // be issuing -- the final header line contains the credentials.
20870 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20871 "Host: www.example.org:443\r\n"
20872 "Proxy-Connection: keep-alive\r\n"
20873 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20874
20875 MockWrite("GET / HTTP/1.1\r\n"
20876 "Host: www.example.org\r\n"
20877 "Connection: keep-alive\r\n\r\n"),
20878 };
20879
20880 MockRead data_reads2[] = {
20881 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20882
20883 MockRead("HTTP/1.1 200 OK\r\n"),
20884 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20885 MockRead("Content-Length: 5\r\n\r\n"),
20886 MockRead(SYNCHRONOUS, "hello"),
20887 };
20888
20889 StaticSocketDataProvider data1(data_reads1, data_writes1);
20890 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20891 StaticSocketDataProvider data2(data_reads2, data_writes2);
20892 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20893 SSLSocketDataProvider ssl(ASYNC, OK);
20894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20895
20896 TestCompletionCallback callback1;
20897
20898 auto trans =
20899 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20900
20901 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20902 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20903
20904 const HttpResponseInfo* response = trans->GetResponseInfo();
20905 EXPECT_EQ(407, response->headers->response_code());
20906
20907 std::string response_data;
20908 rv = ReadTransaction(trans.get(), &response_data);
20909 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20910
20911 // No NEL report is generated for the 407.
20912 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20913
20914 TestCompletionCallback callback2;
20915
20916 rv =
20917 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20918 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20919
20920 response = trans->GetResponseInfo();
20921 EXPECT_EQ(200, response->headers->response_code());
20922
20923 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20924 EXPECT_EQ("hello", response_data);
20925
20926 trans.reset();
20927
20928 // No NEL report is generated because we are behind a proxy.
20929 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20930}
20931
Douglas Creageref5eecdc2018-11-09 20:50:3620932TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20933 ReportContainsUploadDepth) {
20934 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220935 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620936 RequestPolicy();
20937 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220938 const NetworkErrorLoggingService::RequestDetails& error =
20939 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620940 EXPECT_EQ(7, error.reporting_upload_depth);
20941}
20942
Lily Chenfec60d92019-01-24 01:16:4220943TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20944 std::string extra_header_string = extra_headers_.ToString();
20945 static const base::TimeDelta kSleepDuration =
20946 base::TimeDelta::FromMilliseconds(10);
20947
20948 std::vector<MockWrite> data_writes = {
20949 MockWrite(ASYNC, 0,
20950 "GET / HTTP/1.1\r\n"
20951 "Host: www.example.org\r\n"
20952 "Connection: keep-alive\r\n"),
20953 MockWrite(ASYNC, 1, extra_header_string.data()),
20954 };
20955
20956 std::vector<MockRead> data_reads = {
20957 // Write one byte of the status line, followed by a pause.
20958 MockRead(ASYNC, 2, "H"),
20959 MockRead(ASYNC, ERR_IO_PENDING, 3),
20960 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20961 MockRead(ASYNC, 5, "hello world"),
20962 MockRead(SYNCHRONOUS, OK, 6),
20963 };
20964
20965 SequencedSocketData data(data_reads, data_writes);
20966 session_deps_.socket_factory->AddSocketDataProvider(&data);
20967
20968 SSLSocketDataProvider ssl(ASYNC, OK);
20969 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20970
20971 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20972
20973 auto trans =
20974 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20975
20976 TestCompletionCallback callback;
20977
20978 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20980
20981 data.RunUntilPaused();
20982 ASSERT_TRUE(data.IsPaused());
20983 FastForwardBy(kSleepDuration);
20984 data.Resume();
20985
20986 EXPECT_THAT(callback.GetResult(rv), IsOk());
20987
20988 std::string response_data;
20989 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20990 EXPECT_EQ("hello world", response_data);
20991
20992 trans.reset();
20993
Douglas Creageref5eecdc2018-11-09 20:50:3620994 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220995
20996 CheckReport(0 /* index */, 200 /* status_code */, OK);
20997
20998 const NetworkErrorLoggingService::RequestDetails& error =
20999 network_error_logging_service()->errors()[0];
21000
21001 // Sanity-check elapsed time in error report
21002 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3621003}
Lily Chenfec60d92019-01-24 01:16:4221004
Douglas Creager3cb042052018-11-06 23:08:5221005#endif // BUILDFLAG(ENABLE_REPORTING)
21006
Batalov Vladislava4e97a502019-04-11 15:35:2321007TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
21008 HttpRequestInfo request;
21009 request.method = "GET";
21010 request.url = GURL("http://example.org/");
21011
21012 request.load_flags = LOAD_ONLY_FROM_CACHE;
21013
21014 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21015 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21016 TestCompletionCallback callback1;
21017 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
21018
21019 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
21020}
21021
Steven Valdez1c1859172019-04-10 15:33:2821022TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1521023 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821024 HttpRequestInfo request;
21025 request.method = "GET";
21026 request.url = GURL("https://www.example.org/");
21027 request.traffic_annotation =
21028 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21029
21030 MockWrite data_writes[] = {
21031 MockWrite("GET / HTTP/1.1\r\n"
21032 "Host: www.example.org\r\n"
21033 "Connection: keep-alive\r\n\r\n"),
21034 };
21035
Steven Valdez1c1859172019-04-10 15:33:2821036 MockRead data_reads[] = {
21037 MockRead("HTTP/1.1 200 OK\r\n"),
21038 MockRead("Content-Length: 1\r\n\r\n"),
21039 MockRead(SYNCHRONOUS, "1"),
21040 };
21041
21042 StaticSocketDataProvider data(data_reads, data_writes);
21043 session_deps_.socket_factory->AddSocketDataProvider(&data);
21044 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521045 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821046 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521047 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821048 session_deps_.enable_early_data = true;
21049 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21050
21051 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21052
21053 TestCompletionCallback callback;
21054 auto trans =
21055 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21056
David Benjaminbae08ba2019-10-18 21:06:1521057 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821058 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21060
21061 rv = callback.WaitForResult();
21062 EXPECT_THAT(rv, IsOk());
21063
21064 const HttpResponseInfo* response = trans->GetResponseInfo();
21065 ASSERT_TRUE(response);
21066 ASSERT_TRUE(response->headers);
21067 EXPECT_EQ(200, response->headers->response_code());
21068 EXPECT_EQ(1, response->headers->GetContentLength());
21069
21070 // Check that ConfirmHandshake wasn't called.
21071 ASSERT_FALSE(ssl.ConfirmDataConsumed());
21072 ASSERT_TRUE(ssl.WriteBeforeConfirm());
21073
David Benjaminbae08ba2019-10-18 21:06:1521074 // The handshake time should include the time it took to run Connect(), but
21075 // not ConfirmHandshake().
21076 LoadTimingInfo load_timing_info;
21077 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21078 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21079 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21080 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21081 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21082
Steven Valdez1c1859172019-04-10 15:33:2821083 trans.reset();
21084
Matt Menke433de6d2020-03-04 00:24:1121085 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821086}
21087
21088TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521089 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821090 HttpRequestInfo request;
21091 request.method = "POST";
21092 request.url = GURL("https://www.example.org/");
21093 request.traffic_annotation =
21094 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21095
21096 MockWrite data_writes[] = {
21097 MockWrite(SYNCHRONOUS,
21098 "POST / HTTP/1.1\r\n"
21099 "Host: www.example.org\r\n"
21100 "Connection: keep-alive\r\n"
21101 "Content-Length: 0\r\n\r\n"),
21102 };
21103
Steven Valdez1c1859172019-04-10 15:33:2821104 MockRead data_reads[] = {
21105 MockRead("HTTP/1.1 200 OK\r\n"),
21106 MockRead("Content-Length: 1\r\n\r\n"),
21107 MockRead(SYNCHRONOUS, "1"),
21108 };
21109
21110 StaticSocketDataProvider data(data_reads, data_writes);
21111 session_deps_.socket_factory->AddSocketDataProvider(&data);
21112 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521113 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821114 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521115 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821116 session_deps_.enable_early_data = true;
21117 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21118
21119 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21120
21121 TestCompletionCallback callback;
21122 auto trans =
21123 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21124
David Benjaminbae08ba2019-10-18 21:06:1521125 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821126 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21127 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21128
21129 rv = callback.WaitForResult();
21130 EXPECT_THAT(rv, IsOk());
21131
21132 const HttpResponseInfo* response = trans->GetResponseInfo();
21133 ASSERT_TRUE(response);
21134 ASSERT_TRUE(response->headers);
21135 EXPECT_EQ(200, response->headers->response_code());
21136 EXPECT_EQ(1, response->headers->GetContentLength());
21137
21138 // Check that the Write didn't get called before ConfirmHandshake completed.
21139 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21140
David Benjaminbae08ba2019-10-18 21:06:1521141 // The handshake time should include the time it took to run Connect(), but
21142 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
21143 // assume the connection did not negotiate 0-RTT or the handshake was already
21144 // confirmed.
21145 LoadTimingInfo load_timing_info;
21146 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21147 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21148 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21149 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21150 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21151
Steven Valdez1c1859172019-04-10 15:33:2821152 trans.reset();
21153
Matt Menke433de6d2020-03-04 00:24:1121154 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821155}
21156
21157TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
21158 HttpRequestInfo request;
21159 request.method = "POST";
21160 request.url = GURL("https://www.example.org/");
21161 request.traffic_annotation =
21162 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21163
21164 MockWrite data_writes[] = {
21165 MockWrite(ASYNC,
21166 "POST / HTTP/1.1\r\n"
21167 "Host: www.example.org\r\n"
21168 "Connection: keep-alive\r\n"
21169 "Content-Length: 0\r\n\r\n"),
21170 };
21171
Steven Valdez1c1859172019-04-10 15:33:2821172 MockRead data_reads[] = {
21173 MockRead("HTTP/1.1 200 OK\r\n"),
21174 MockRead("Content-Length: 1\r\n\r\n"),
21175 MockRead(SYNCHRONOUS, "1"),
21176 };
21177
21178 StaticSocketDataProvider data(data_reads, data_writes);
21179 session_deps_.socket_factory->AddSocketDataProvider(&data);
21180 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21181 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
21182 session_deps_.enable_early_data = true;
21183 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21184
21185 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21186
21187 TestCompletionCallback callback;
21188 auto trans =
21189 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21190
21191 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21193
21194 rv = callback.WaitForResult();
21195 EXPECT_THAT(rv, IsOk());
21196
21197 const HttpResponseInfo* response = trans->GetResponseInfo();
21198 ASSERT_TRUE(response);
21199 ASSERT_TRUE(response->headers);
21200 EXPECT_EQ(200, response->headers->response_code());
21201 EXPECT_EQ(1, response->headers->GetContentLength());
21202
21203 // Check that the Write didn't get called before ConfirmHandshake completed.
21204 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21205
21206 trans.reset();
21207
Matt Menke433de6d2020-03-04 00:24:1121208 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821209}
21210
21211TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521212 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821213 HttpRequestInfo request;
21214 request.method = "POST";
21215 request.url = GURL("https://www.example.org/");
21216 request.traffic_annotation =
21217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21218
21219 MockWrite data_writes[] = {
21220 MockWrite(SYNCHRONOUS,
21221 "POST / HTTP/1.1\r\n"
21222 "Host: www.example.org\r\n"
21223 "Connection: keep-alive\r\n"
21224 "Content-Length: 0\r\n\r\n"),
21225 };
21226
Steven Valdez1c1859172019-04-10 15:33:2821227 MockRead data_reads[] = {
21228 MockRead("HTTP/1.1 200 OK\r\n"),
21229 MockRead("Content-Length: 1\r\n\r\n"),
21230 MockRead(SYNCHRONOUS, "1"),
21231 };
21232
21233 StaticSocketDataProvider data(data_reads, data_writes);
21234 session_deps_.socket_factory->AddSocketDataProvider(&data);
21235 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521236 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821237 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1521238 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821239 session_deps_.enable_early_data = true;
21240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21241
21242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21243
21244 TestCompletionCallback callback;
21245 auto trans =
21246 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21247
David Benjaminbae08ba2019-10-18 21:06:1521248 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821249 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21250 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21251
21252 rv = callback.WaitForResult();
21253 EXPECT_THAT(rv, IsOk());
21254
21255 const HttpResponseInfo* response = trans->GetResponseInfo();
21256 ASSERT_TRUE(response);
21257 ASSERT_TRUE(response->headers);
21258 EXPECT_EQ(200, response->headers->response_code());
21259 EXPECT_EQ(1, response->headers->GetContentLength());
21260
21261 // Check that the Write didn't get called before ConfirmHandshake completed.
21262 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21263
David Benjaminbae08ba2019-10-18 21:06:1521264 // The handshake time should include the time it took to run Connect() and
21265 // ConfirmHandshake().
21266 LoadTimingInfo load_timing_info;
21267 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21268 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21269 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21270 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
21271 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
21272 start_time + 2 * kDelay);
21273
Steven Valdez1c1859172019-04-10 15:33:2821274 trans.reset();
21275
Matt Menke433de6d2020-03-04 00:24:1121276 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821277}
21278
21279TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
21280 HttpRequestInfo request;
21281 request.method = "POST";
21282 request.url = GURL("https://www.example.org/");
21283 request.traffic_annotation =
21284 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21285
21286 MockWrite data_writes[] = {
21287 MockWrite(ASYNC,
21288 "POST / HTTP/1.1\r\n"
21289 "Host: www.example.org\r\n"
21290 "Connection: keep-alive\r\n"
21291 "Content-Length: 0\r\n\r\n"),
21292 };
21293
Steven Valdez1c1859172019-04-10 15:33:2821294 MockRead data_reads[] = {
21295 MockRead("HTTP/1.1 200 OK\r\n"),
21296 MockRead("Content-Length: 1\r\n\r\n"),
21297 MockRead(SYNCHRONOUS, "1"),
21298 };
21299
21300 StaticSocketDataProvider data(data_reads, data_writes);
21301 session_deps_.socket_factory->AddSocketDataProvider(&data);
21302 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21303 ssl.confirm = MockConfirm(ASYNC, OK);
21304 session_deps_.enable_early_data = true;
21305 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21306
21307 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21308
21309 TestCompletionCallback callback;
21310 auto trans =
21311 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21312
21313 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21314 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21315
21316 rv = callback.WaitForResult();
21317 EXPECT_THAT(rv, IsOk());
21318
21319 const HttpResponseInfo* response = trans->GetResponseInfo();
21320 ASSERT_TRUE(response);
21321 ASSERT_TRUE(response->headers);
21322 EXPECT_EQ(200, response->headers->response_code());
21323 EXPECT_EQ(1, response->headers->GetContentLength());
21324
21325 // Check that the Write didn't get called before ConfirmHandshake completed.
21326 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21327
21328 trans.reset();
21329
Matt Menke433de6d2020-03-04 00:24:1121330 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821331}
21332
David Benjaminfb976932019-05-15 13:39:1521333// 0-RTT rejects are handled at HttpNetworkTransaction.
21334TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
21335 enum class RejectType {
21336 kRead,
21337 kWrite,
21338 kConfirm,
21339 };
21340
21341 for (RejectType type :
21342 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
21343 SCOPED_TRACE(static_cast<int>(type));
21344 for (Error reject_error :
21345 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
21346 SCOPED_TRACE(reject_error);
21347 session_deps_.socket_factory =
21348 std::make_unique<MockClientSocketFactory>();
21349
21350 HttpRequestInfo request;
21351 request.method = type == RejectType::kConfirm ? "POST" : "GET";
21352 request.url = GURL("https://www.example.org/");
21353 request.traffic_annotation =
21354 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21355
21356 // The first request fails.
21357 std::vector<MockWrite> data1_writes;
21358 std::vector<MockRead> data1_reads;
21359 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
21360 switch (type) {
21361 case RejectType::kRead:
21362 data1_writes.emplace_back(
21363 "GET / HTTP/1.1\r\n"
21364 "Host: www.example.org\r\n"
21365 "Connection: keep-alive\r\n\r\n");
21366 data1_reads.emplace_back(ASYNC, reject_error);
21367 // Cause ConfirmHandshake to hang (it should not be called).
21368 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21369 break;
21370 case RejectType::kWrite:
21371 data1_writes.emplace_back(ASYNC, reject_error);
21372 // Cause ConfirmHandshake to hang (it should not be called).
21373 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21374 break;
21375 case RejectType::kConfirm:
21376 // The request never gets far enough to read or write.
21377 ssl1.confirm = MockConfirm(ASYNC, reject_error);
21378 break;
21379 }
21380
21381 StaticSocketDataProvider data1(data1_reads, data1_writes);
21382 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21383 session_deps_.enable_early_data = true;
21384 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21385
21386 // The retry succeeds.
21387 //
21388 // TODO(https://crbug.com/950705): If |reject_error| is
21389 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
21390 MockWrite data2_writes[] = {
21391 request.method == "POST"
21392 ? MockWrite("POST / HTTP/1.1\r\n"
21393 "Host: www.example.org\r\n"
21394 "Connection: keep-alive\r\n"
21395 "Content-Length: 0\r\n\r\n")
21396 : MockWrite("GET / HTTP/1.1\r\n"
21397 "Host: www.example.org\r\n"
21398 "Connection: keep-alive\r\n\r\n"),
21399 };
21400
21401 MockRead data2_reads[] = {
21402 MockRead("HTTP/1.1 200 OK\r\n"),
21403 MockRead("Content-Length: 1\r\n\r\n"),
21404 MockRead(SYNCHRONOUS, "1"),
21405 };
21406
21407 StaticSocketDataProvider data2(data2_reads, data2_writes);
21408 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21409 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21410 ssl2.confirm = MockConfirm(ASYNC, OK);
21411 session_deps_.enable_early_data = true;
21412 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21413
21414 std::unique_ptr<HttpNetworkSession> session(
21415 CreateSession(&session_deps_));
21416
21417 TestCompletionCallback callback;
21418 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21419 session.get());
21420
21421 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21422 NetLogWithSource())),
21423 IsOk());
21424
21425 const HttpResponseInfo* response = trans->GetResponseInfo();
21426 ASSERT_TRUE(response);
21427 ASSERT_TRUE(response->headers);
21428 EXPECT_EQ(200, response->headers->response_code());
21429 EXPECT_EQ(1, response->headers->GetContentLength());
21430 }
21431 }
21432}
21433
Steven Valdez1c1859172019-04-10 15:33:2821434TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21435 HttpRequestInfo request;
21436 request.method = "POST";
21437 request.url = GURL("https://www.example.org/");
21438 request.traffic_annotation =
21439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21440
21441 MockWrite data_writes[] = {
21442 MockWrite("POST / HTTP/1.1\r\n"
21443 "Host: www.example.org\r\n"
21444 "Connection: keep-alive\r\n"
21445 "Content-Length: 0\r\n\r\n"),
21446 };
21447
Steven Valdez1c1859172019-04-10 15:33:2821448 MockRead data_reads[] = {
21449 MockRead("HTTP/1.1 200 OK\r\n"),
21450 MockRead("Content-Length: 1\r\n\r\n"),
21451 MockRead(SYNCHRONOUS, "1"),
21452 };
21453
21454 StaticSocketDataProvider data(data_reads, data_writes);
21455 session_deps_.socket_factory->AddSocketDataProvider(&data);
21456 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21457 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21458 session_deps_.enable_early_data = true;
21459 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21460
21461 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21462
21463 TestCompletionCallback callback;
21464 auto trans =
21465 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21466
21467 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21468 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21469
21470 rv = callback.WaitForResult();
21471 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21472
21473 // Check that the Write didn't get called before ConfirmHandshake completed.
21474 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21475
21476 trans.reset();
21477
Matt Menke433de6d2020-03-04 00:24:1121478 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821479}
21480
21481TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21482 HttpRequestInfo request;
21483 request.method = "POST";
21484 request.url = GURL("https://www.example.org/");
21485 request.traffic_annotation =
21486 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21487
21488 MockWrite data_writes[] = {
21489 MockWrite("POST / HTTP/1.1\r\n"
21490 "Host: www.example.org\r\n"
21491 "Connection: keep-alive\r\n"
21492 "Content-Length: 0\r\n\r\n"),
21493 };
21494
Steven Valdez1c1859172019-04-10 15:33:2821495 MockRead data_reads[] = {
21496 MockRead("HTTP/1.1 200 OK\r\n"),
21497 MockRead("Content-Length: 1\r\n\r\n"),
21498 MockRead(SYNCHRONOUS, "1"),
21499 };
21500
21501 StaticSocketDataProvider data(data_reads, data_writes);
21502 session_deps_.socket_factory->AddSocketDataProvider(&data);
21503 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21504 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21505 session_deps_.enable_early_data = true;
21506 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21507
21508 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21509
21510 TestCompletionCallback callback;
21511 auto trans =
21512 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21513
21514 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21515 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21516
21517 rv = callback.WaitForResult();
21518 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21519
21520 // Check that the Write didn't get called before ConfirmHandshake completed.
21521 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21522
21523 trans.reset();
21524
Matt Menke433de6d2020-03-04 00:24:1121525 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821526}
21527
David Benjamin2eb827f2019-04-29 18:31:0421528// Test the proxy and origin server each requesting both TLS client certificates
21529// and HTTP auth. This is a regression test for https://crbug.com/946406.
21530TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21531 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621532 session_deps_.proxy_resolution_service =
21533 ConfiguredProxyResolutionService::CreateFixed(
21534 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421535
21536 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21537 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21538
21539 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21540 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21541 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21542 ASSERT_TRUE(identity_proxy);
21543
21544 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21545 cert_request_info_origin->host_and_port =
21546 HostPortPair("www.example.org", 443);
21547
21548 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21549 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21550 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21551 ASSERT_TRUE(identity_origin);
21552
21553 HttpRequestInfo request;
21554 request.method = "GET";
21555 request.url = GURL("https://www.example.org/");
21556 request.traffic_annotation =
21557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21558
David Benjamin7ebab032019-04-30 21:51:3021559 // First, the client connects to the proxy, which requests a client
21560 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421561 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21562 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21563 ssl_proxy1.expected_send_client_cert = false;
21564 StaticSocketDataProvider data1;
21565 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421567
David Benjamin7ebab032019-04-30 21:51:3021568 // The client responds with a certificate on a new connection. The handshake
21569 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421570 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21571 ssl_proxy2.expected_send_client_cert = true;
21572 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021573 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421574 std::vector<MockWrite> mock_writes2;
21575 std::vector<MockRead> mock_reads2;
21576 mock_writes2.emplace_back(
21577 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21578 "Host: www.example.org:443\r\n"
21579 "Proxy-Connection: keep-alive\r\n\r\n");
21580 mock_reads2.emplace_back(
21581 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21582 "Content-Length: 0\r\n"
21583 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021584 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421585 mock_writes2.emplace_back(
21586 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21587 "Host: www.example.org:443\r\n"
21588 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021589 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421590 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21591 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21592 // The origin requests client certificates.
21593 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21594 ssl_origin2.cert_request_info = cert_request_info_origin.get();
21595 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21596 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021597 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421599
David Benjamin7ebab032019-04-30 21:51:3021600 // The client responds to the origin client certificate request on a new
21601 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421602 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21603 ssl_proxy3.expected_send_client_cert = true;
21604 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21605 std::vector<MockWrite> mock_writes3;
21606 std::vector<MockRead> mock_reads3;
21607 mock_writes3.emplace_back(
21608 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21609 "Host: www.example.org:443\r\n"
21610 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021611 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421612 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21613 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21614 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21615 ssl_origin3.expected_send_client_cert = true;
21616 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021617 // The client sends the origin HTTP request, which results in another HTTP
21618 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421619 mock_writes3.emplace_back(
21620 "GET / HTTP/1.1\r\n"
21621 "Host: www.example.org\r\n"
21622 "Connection: keep-alive\r\n\r\n");
21623 mock_reads3.emplace_back(
21624 "HTTP/1.1 401 Unauthorized\r\n"
21625 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21626 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021627 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421628 mock_writes3.emplace_back(
21629 "GET / HTTP/1.1\r\n"
21630 "Host: www.example.org\r\n"
21631 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021632 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421633 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21634 mock_reads3.emplace_back(
21635 "HTTP/1.1 200 OK\r\n"
21636 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121637 // The client makes another request. This should reuse the socket with all
21638 // credentials cached.
21639 mock_writes3.emplace_back(
21640 "GET / HTTP/1.1\r\n"
21641 "Host: www.example.org\r\n"
21642 "Connection: keep-alive\r\n"
21643 // Authenticate as user:pass.
21644 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21645 mock_reads3.emplace_back(
21646 "HTTP/1.1 200 OK\r\n"
21647 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421648 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21649 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021650 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421652
21653 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21654
21655 // Start the request.
21656 TestCompletionCallback callback;
21657 auto trans =
21658 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21659 int rv = callback.GetResult(
21660 trans->Start(&request, callback.callback(), NetLogWithSource()));
21661
21662 // Handle the proxy client certificate challenge.
21663 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21664 SSLCertRequestInfo* cert_request_info =
21665 trans->GetResponseInfo()->cert_request_info.get();
21666 ASSERT_TRUE(cert_request_info);
21667 EXPECT_TRUE(cert_request_info->is_proxy);
21668 EXPECT_EQ(cert_request_info->host_and_port,
21669 cert_request_info_proxy->host_and_port);
21670 rv = callback.GetResult(trans->RestartWithCertificate(
21671 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21672 callback.callback()));
21673
21674 // Handle the proxy HTTP auth challenge.
21675 ASSERT_THAT(rv, IsOk());
21676 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21677 EXPECT_TRUE(
21678 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21679 rv = callback.GetResult(trans->RestartWithAuth(
21680 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21681 callback.callback()));
21682
21683 // Handle the origin client certificate challenge.
21684 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21685 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21686 ASSERT_TRUE(cert_request_info);
21687 EXPECT_FALSE(cert_request_info->is_proxy);
21688 EXPECT_EQ(cert_request_info->host_and_port,
21689 cert_request_info_origin->host_and_port);
21690 rv = callback.GetResult(trans->RestartWithCertificate(
21691 identity_origin->certificate(), identity_origin->ssl_private_key(),
21692 callback.callback()));
21693
21694 // Handle the origin HTTP auth challenge.
21695 ASSERT_THAT(rv, IsOk());
21696 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21697 EXPECT_TRUE(
21698 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21699 rv = callback.GetResult(trans->RestartWithAuth(
21700 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21701 callback.callback()));
21702
21703 // The request completes.
21704 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021705 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121706
21707 // Make a second request. This time all credentials are cached.
21708 trans =
21709 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21710 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21711 NetLogWithSource())),
21712 IsOk());
21713 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421714}
21715
21716// Test the proxy and origin server each requesting both TLS client certificates
21717// and HTTP auth and each HTTP auth closing the connection. This is a regression
21718// test for https://crbug.com/946406.
21719TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21720 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621721 session_deps_.proxy_resolution_service =
21722 ConfiguredProxyResolutionService::CreateFixed(
21723 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421724
21725 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21726 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21727
21728 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21729 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21730 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21731 ASSERT_TRUE(identity_proxy);
21732
21733 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21734 cert_request_info_origin->host_and_port =
21735 HostPortPair("www.example.org", 443);
21736
21737 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21738 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21739 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21740 ASSERT_TRUE(identity_origin);
21741
21742 HttpRequestInfo request;
21743 request.method = "GET";
21744 request.url = GURL("https://www.example.org/");
21745 request.traffic_annotation =
21746 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21747
David Benjamin7ebab032019-04-30 21:51:3021748 // First, the client connects to the proxy, which requests a client
21749 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421750 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21751 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21752 ssl_proxy1.expected_send_client_cert = false;
21753 StaticSocketDataProvider data1;
21754 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021755 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421756
David Benjamin7ebab032019-04-30 21:51:3021757 // The client responds with a certificate on a new connection. The handshake
21758 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421759 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21760 ssl_proxy2.expected_send_client_cert = true;
21761 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021762 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421763 std::vector<MockWrite> mock_writes2;
21764 std::vector<MockRead> mock_reads2;
21765 mock_writes2.emplace_back(
21766 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21767 "Host: www.example.org:443\r\n"
21768 "Proxy-Connection: keep-alive\r\n\r\n");
21769 mock_reads2.emplace_back(
21770 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21771 "Content-Length: 0\r\n"
21772 "Proxy-Connection: close\r\n"
21773 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21774 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21775 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421777
David Benjamin7ebab032019-04-30 21:51:3021778 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421779 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21780 ssl_proxy3.expected_send_client_cert = true;
21781 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21782 std::vector<MockWrite> mock_writes3;
21783 std::vector<MockRead> mock_reads3;
21784 mock_writes3.emplace_back(
21785 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21786 "Host: www.example.org:443\r\n"
21787 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021788 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421789 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21790 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21791 // The origin requests client certificates.
21792 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21793 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21794 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21795 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021796 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21797 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421798
David Benjamin7ebab032019-04-30 21:51:3021799 // The client responds to the origin client certificate request on a new
21800 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421801 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21802 ssl_proxy4.expected_send_client_cert = true;
21803 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21804 std::vector<MockWrite> mock_writes4;
21805 std::vector<MockRead> mock_reads4;
21806 mock_writes4.emplace_back(
21807 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21808 "Host: www.example.org:443\r\n"
21809 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021810 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421811 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21812 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21813 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21814 ssl_origin4.expected_send_client_cert = true;
21815 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021816 // The client sends the origin HTTP request, which results in another HTTP
21817 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421818 mock_writes4.emplace_back(
21819 "GET / HTTP/1.1\r\n"
21820 "Host: www.example.org\r\n"
21821 "Connection: keep-alive\r\n\r\n");
21822 mock_reads4.emplace_back(
21823 "HTTP/1.1 401 Unauthorized\r\n"
21824 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21825 "Connection: close\r\n"
21826 "Content-Length: 0\r\n\r\n");
21827 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21828 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021829 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21830 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421831
David Benjamin7ebab032019-04-30 21:51:3021832 // The client retries with credentials on a new connection, and the request
21833 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421834 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21835 ssl_proxy5.expected_send_client_cert = true;
21836 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21837 std::vector<MockWrite> mock_writes5;
21838 std::vector<MockRead> mock_reads5;
21839 mock_writes5.emplace_back(
21840 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21841 "Host: www.example.org:443\r\n"
21842 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021843 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421844 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21845 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21846 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21847 ssl_origin5.expected_send_client_cert = true;
21848 ssl_origin5.expected_client_cert = identity_origin->certificate();
21849 mock_writes5.emplace_back(
21850 "GET / HTTP/1.1\r\n"
21851 "Host: www.example.org\r\n"
21852 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021853 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421854 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21855 mock_reads5.emplace_back(
21856 "HTTP/1.1 200 OK\r\n"
21857 "Connection: close\r\n"
21858 "Content-Length: 0\r\n\r\n");
21859 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21860 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021861 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21862 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421863
David Benjaminbac8dff2019-08-07 01:30:4121864 // The client makes a second request. This needs yet another connection, but
21865 // all credentials are cached.
21866 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21867 ssl_proxy6.expected_send_client_cert = true;
21868 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21869 std::vector<MockWrite> mock_writes6;
21870 std::vector<MockRead> mock_reads6;
21871 mock_writes6.emplace_back(
21872 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21873 "Host: www.example.org:443\r\n"
21874 "Proxy-Connection: keep-alive\r\n"
21875 // Authenticate as proxyuser:proxypass.
21876 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21877 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21878 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21879 ssl_origin6.expected_send_client_cert = true;
21880 ssl_origin6.expected_client_cert = identity_origin->certificate();
21881 mock_writes6.emplace_back(
21882 "GET / HTTP/1.1\r\n"
21883 "Host: www.example.org\r\n"
21884 "Connection: keep-alive\r\n"
21885 // Authenticate as user:pass.
21886 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21887 mock_reads6.emplace_back(
21888 "HTTP/1.1 200 OK\r\n"
21889 "Connection: close\r\n"
21890 "Content-Length: 0\r\n\r\n");
21891 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21892 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21895
David Benjamin2eb827f2019-04-29 18:31:0421896 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21897
21898 // Start the request.
21899 TestCompletionCallback callback;
21900 auto trans =
21901 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21902 int rv = callback.GetResult(
21903 trans->Start(&request, callback.callback(), NetLogWithSource()));
21904
21905 // Handle the proxy client certificate challenge.
21906 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21907 SSLCertRequestInfo* cert_request_info =
21908 trans->GetResponseInfo()->cert_request_info.get();
21909 ASSERT_TRUE(cert_request_info);
21910 EXPECT_TRUE(cert_request_info->is_proxy);
21911 EXPECT_EQ(cert_request_info->host_and_port,
21912 cert_request_info_proxy->host_and_port);
21913 rv = callback.GetResult(trans->RestartWithCertificate(
21914 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21915 callback.callback()));
21916
21917 // Handle the proxy HTTP auth challenge.
21918 ASSERT_THAT(rv, IsOk());
21919 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21920 EXPECT_TRUE(
21921 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21922 rv = callback.GetResult(trans->RestartWithAuth(
21923 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21924 callback.callback()));
21925
21926 // Handle the origin client certificate challenge.
21927 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21928 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21929 ASSERT_TRUE(cert_request_info);
21930 EXPECT_FALSE(cert_request_info->is_proxy);
21931 EXPECT_EQ(cert_request_info->host_and_port,
21932 cert_request_info_origin->host_and_port);
21933 rv = callback.GetResult(trans->RestartWithCertificate(
21934 identity_origin->certificate(), identity_origin->ssl_private_key(),
21935 callback.callback()));
21936
21937 // Handle the origin HTTP auth challenge.
21938 ASSERT_THAT(rv, IsOk());
21939 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21940 EXPECT_TRUE(
21941 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21942 rv = callback.GetResult(trans->RestartWithAuth(
21943 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21944 callback.callback()));
21945
21946 // The request completes.
21947 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021948 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121949
21950 // Make a second request. This time all credentials are cached.
21951 trans =
21952 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21953 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21954 NetLogWithSource())),
21955 IsOk());
21956 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021957}
21958
21959// Test the proxy requesting HTTP auth and the server requesting TLS client
21960// certificates. This is a regression test for https://crbug.com/946406.
21961TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21962 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621963 session_deps_.proxy_resolution_service =
21964 ConfiguredProxyResolutionService::CreateFixed(
21965 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin7ebab032019-04-30 21:51:3021966
21967 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21968 cert_request_info_origin->host_and_port =
21969 HostPortPair("www.example.org", 443);
21970
21971 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21972 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21973 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21974 ASSERT_TRUE(identity_origin);
21975
21976 HttpRequestInfo request;
21977 request.method = "GET";
21978 request.url = GURL("https://www.example.org/");
21979 request.traffic_annotation =
21980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21981
21982 // The client connects to the proxy. The handshake succeeds.
21983 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21984 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21985 std::vector<MockWrite> mock_writes1;
21986 std::vector<MockRead> mock_reads1;
21987 mock_writes1.emplace_back(
21988 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21989 "Host: www.example.org:443\r\n"
21990 "Proxy-Connection: keep-alive\r\n\r\n");
21991 mock_reads1.emplace_back(
21992 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21993 "Content-Length: 0\r\n"
21994 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21995 // The client retries with credentials, and the request finally succeeds.
21996 mock_writes1.emplace_back(
21997 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21998 "Host: www.example.org:443\r\n"
21999 "Proxy-Connection: keep-alive\r\n"
22000 // Authenticate as proxyuser:proxypass.
22001 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
22002 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
22003 // The origin requests client certificates.
22004 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
22005 ssl_origin1.cert_request_info = cert_request_info_origin.get();
22006 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
22007 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22009 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22010
22011 // The client responds to the origin client certificate request on a new
22012 // connection.
22013 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22014 std::vector<MockWrite> mock_writes2;
22015 std::vector<MockRead> mock_reads2;
22016 mock_writes2.emplace_back(
22017 "CONNECT www.example.org:443 HTTP/1.1\r\n"
22018 "Host: www.example.org:443\r\n"
22019 "Proxy-Connection: keep-alive\r\n"
22020 // Authenticate as proxyuser:proxypass.
22021 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
22022 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
22023 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
22024 ssl_origin2.expected_send_client_cert = true;
22025 ssl_origin2.expected_client_cert = identity_origin->certificate();
22026 // The client sends the origin HTTP request, which succeeds.
22027 mock_writes2.emplace_back(
22028 "GET / HTTP/1.1\r\n"
22029 "Host: www.example.org\r\n"
22030 "Connection: keep-alive\r\n\r\n");
22031 mock_reads2.emplace_back(
22032 "HTTP/1.1 200 OK\r\n"
22033 "Content-Length: 0\r\n\r\n");
22034 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
22035 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22037 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
22038
22039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22040
22041 // Start the request.
22042 TestCompletionCallback callback;
22043 auto trans =
22044 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22045 int rv = callback.GetResult(
22046 trans->Start(&request, callback.callback(), NetLogWithSource()));
22047
22048 // Handle the proxy HTTP auth challenge.
22049 ASSERT_THAT(rv, IsOk());
22050 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
22051 EXPECT_TRUE(
22052 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
22053 rv = callback.GetResult(trans->RestartWithAuth(
22054 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
22055 callback.callback()));
22056
22057 // Handle the origin client certificate challenge.
22058 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22059 SSLCertRequestInfo* cert_request_info =
22060 trans->GetResponseInfo()->cert_request_info.get();
22061 ASSERT_TRUE(cert_request_info);
22062 EXPECT_FALSE(cert_request_info->is_proxy);
22063 EXPECT_EQ(cert_request_info->host_and_port,
22064 cert_request_info_origin->host_and_port);
22065 rv = callback.GetResult(trans->RestartWithCertificate(
22066 identity_origin->certificate(), identity_origin->ssl_private_key(),
22067 callback.callback()));
22068
22069 // The request completes.
22070 ASSERT_THAT(rv, IsOk());
22071 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0422072}
22073
David Benjamin6e673a82019-04-30 22:52:5822074// Test that socket reuse works with client certificates.
22075TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
22076 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22077 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
22078
22079 std::unique_ptr<FakeClientCertIdentity> identity =
22080 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22081 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22082 ASSERT_TRUE(identity);
22083
22084 HttpRequestInfo request1;
22085 request1.method = "GET";
22086 request1.url = GURL("https://www.example.org/a");
22087 request1.traffic_annotation =
22088 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22089
22090 HttpRequestInfo request2;
22091 request2.method = "GET";
22092 request2.url = GURL("https://www.example.org/b");
22093 request2.traffic_annotation =
22094 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22095
22096 // The first connection results in a client certificate request.
22097 StaticSocketDataProvider data1;
22098 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22099 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
22100 ssl1.cert_request_info = cert_request_info.get();
22101 ssl1.expected_send_client_cert = false;
22102 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22103
22104 // The second connection succeeds and is usable for both requests.
22105 MockWrite mock_writes[] = {
22106 MockWrite("GET /a HTTP/1.1\r\n"
22107 "Host: www.example.org\r\n"
22108 "Connection: keep-alive\r\n\r\n"),
22109 MockWrite("GET /b HTTP/1.1\r\n"
22110 "Host: www.example.org\r\n"
22111 "Connection: keep-alive\r\n\r\n"),
22112 };
22113 MockRead mock_reads[] = {
22114 MockRead("HTTP/1.1 200 OK\r\n"
22115 "Content-Length: 0\r\n\r\n"),
22116 MockRead("HTTP/1.1 200 OK\r\n"
22117 "Content-Length: 0\r\n\r\n"),
22118 };
22119 StaticSocketDataProvider data2(mock_reads, mock_writes);
22120 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22121 SSLSocketDataProvider ssl2(ASYNC, OK);
22122 ssl2.expected_send_client_cert = true;
22123 ssl2.expected_client_cert = identity->certificate();
22124 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22125
22126 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22127
22128 // Start the first request. It succeeds after providing client certificates.
22129 TestCompletionCallback callback;
22130 auto trans =
22131 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22132 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
22133 NetLogWithSource())),
22134 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22135
22136 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
22137 ASSERT_TRUE(info);
22138 EXPECT_FALSE(info->is_proxy);
22139 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
22140
22141 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
22142 identity->certificate(), identity->ssl_private_key(),
22143 callback.callback())),
22144 IsOk());
22145 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22146
22147 // Make the second request. It completes without requesting client
22148 // certificates.
22149 trans =
22150 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22151 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
22152 NetLogWithSource())),
22153 IsOk());
22154 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22155}
22156
Matt Menke166443c2019-05-24 18:45:5922157// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
22158// sequence with two different NetworkIsolationKeys, the first and last have the
22159// same key, the second a different one. Checks that the requests are
22160// partitioned across sockets as expected.
22161TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Matt Menke4807a9a2020-11-21 00:14:4122162 const SchemefulSite kSite1(GURL("http://origin1/"));
22163 const SchemefulSite kSite2(GURL("http://origin2/"));
22164 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
22165 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
Matt Menke166443c2019-05-24 18:45:5922166
22167 for (bool partition_connections : {false, true}) {
22168 SCOPED_TRACE(partition_connections);
22169
22170 base::test::ScopedFeatureList feature_list;
22171 if (partition_connections) {
22172 feature_list.InitAndEnableFeature(
22173 features::kPartitionConnectionsByNetworkIsolationKey);
22174 } else {
22175 feature_list.InitAndDisableFeature(
22176 features::kPartitionConnectionsByNetworkIsolationKey);
22177 }
22178
22179 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22180
22181 // Reads and writes for the unpartitioned case, where only one socket is
22182 // used.
22183
22184 const MockWrite kUnpartitionedWrites[] = {
22185 MockWrite("GET /1 HTTP/1.1\r\n"
22186 "Host: foo.test\r\n"
22187 "Connection: keep-alive\r\n\r\n"),
22188 MockWrite("GET /2 HTTP/1.1\r\n"
22189 "Host: foo.test\r\n"
22190 "Connection: keep-alive\r\n\r\n"),
22191 MockWrite("GET /3 HTTP/1.1\r\n"
22192 "Host: foo.test\r\n"
22193 "Connection: keep-alive\r\n\r\n"),
22194 };
22195
22196 const MockRead kUnpartitionedReads[] = {
22197 MockRead("HTTP/1.1 200 OK\r\n"
22198 "Connection: keep-alive\r\n"
22199 "Content-Length: 1\r\n\r\n"
22200 "1"),
22201 MockRead("HTTP/1.1 200 OK\r\n"
22202 "Connection: keep-alive\r\n"
22203 "Content-Length: 1\r\n\r\n"
22204 "2"),
22205 MockRead("HTTP/1.1 200 OK\r\n"
22206 "Connection: keep-alive\r\n"
22207 "Content-Length: 1\r\n\r\n"
22208 "3"),
22209 };
22210
22211 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
22212 kUnpartitionedWrites);
22213
22214 // Reads and writes for the partitioned case, where two sockets are used.
22215
22216 const MockWrite kPartitionedWrites1[] = {
22217 MockWrite("GET /1 HTTP/1.1\r\n"
22218 "Host: foo.test\r\n"
22219 "Connection: keep-alive\r\n\r\n"),
22220 MockWrite("GET /3 HTTP/1.1\r\n"
22221 "Host: foo.test\r\n"
22222 "Connection: keep-alive\r\n\r\n"),
22223 };
22224
22225 const MockRead kPartitionedReads1[] = {
22226 MockRead("HTTP/1.1 200 OK\r\n"
22227 "Connection: keep-alive\r\n"
22228 "Content-Length: 1\r\n\r\n"
22229 "1"),
22230 MockRead("HTTP/1.1 200 OK\r\n"
22231 "Connection: keep-alive\r\n"
22232 "Content-Length: 1\r\n\r\n"
22233 "3"),
22234 };
22235
22236 const MockWrite kPartitionedWrites2[] = {
22237 MockWrite("GET /2 HTTP/1.1\r\n"
22238 "Host: foo.test\r\n"
22239 "Connection: keep-alive\r\n\r\n"),
22240 };
22241
22242 const MockRead kPartitionedReads2[] = {
22243 MockRead("HTTP/1.1 200 OK\r\n"
22244 "Connection: keep-alive\r\n"
22245 "Content-Length: 1\r\n\r\n"
22246 "2"),
22247 };
22248
22249 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
22250 kPartitionedWrites1);
22251 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
22252 kPartitionedWrites2);
22253
22254 if (partition_connections) {
22255 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22256 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22257 } else {
22258 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
22259 }
22260
22261 TestCompletionCallback callback;
22262 HttpRequestInfo request1;
22263 request1.method = "GET";
22264 request1.url = GURL("http://foo.test/1");
22265 request1.traffic_annotation =
22266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22267 request1.network_isolation_key = network_isolation_key1;
22268 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22269 session.get());
22270 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22271 EXPECT_THAT(callback.GetResult(rv), IsOk());
22272 std::string response_data1;
22273 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22274 EXPECT_EQ("1", response_data1);
22275 trans1.reset();
22276
22277 HttpRequestInfo request2;
22278 request2.method = "GET";
22279 request2.url = GURL("http://foo.test/2");
22280 request2.traffic_annotation =
22281 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22282 request2.network_isolation_key = network_isolation_key2;
22283 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22284 session.get());
22285 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22286 EXPECT_THAT(callback.GetResult(rv), IsOk());
22287 std::string response_data2;
22288 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22289 EXPECT_EQ("2", response_data2);
22290 trans2.reset();
22291
22292 HttpRequestInfo request3;
22293 request3.method = "GET";
22294 request3.url = GURL("http://foo.test/3");
22295 request3.traffic_annotation =
22296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22297 request3.network_isolation_key = network_isolation_key1;
22298 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22299 session.get());
22300 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22301 EXPECT_THAT(callback.GetResult(rv), IsOk());
22302 std::string response_data3;
22303 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22304 EXPECT_EQ("3", response_data3);
22305 trans3.reset();
22306 }
22307}
22308
Matt Menkeae58eeb2019-05-24 21:09:5022309TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Matt Menke4807a9a2020-11-21 00:14:4122310 const SchemefulSite kSite1(GURL("http://origin1/"));
22311 const SchemefulSite kSite2(GURL("http://origin2/"));
22312 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
22313 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
Matt Menkeae58eeb2019-05-24 21:09:5022314
22315 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
22316 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
22317 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
22318 // the same way as the HTTP over H2 proxy case.
22319 for (bool use_proxy : {false, true}) {
22320 SCOPED_TRACE(use_proxy);
22321 if (use_proxy) {
22322 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622323 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkeae58eeb2019-05-24 21:09:5022324 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
22325 } else {
22326 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622327 ConfiguredProxyResolutionService::CreateDirect();
Matt Menkeae58eeb2019-05-24 21:09:5022328 }
22329 const char* url1 = nullptr;
22330 const char* url2 = nullptr;
22331 const char* url3 = nullptr;
22332 if (use_proxy) {
22333 url1 = "http://foo.test/1";
22334 url2 = "http://foo.test/2";
22335 url3 = "http://foo.test/3";
22336 } else {
22337 url1 = "https://foo.test/1";
22338 url2 = "https://foo.test/2";
22339 url3 = "https://foo.test/3";
22340 }
22341
22342 for (bool partition_connections : {false, true}) {
22343 SCOPED_TRACE(partition_connections);
22344
22345 base::test::ScopedFeatureList feature_list;
22346 if (partition_connections) {
22347 feature_list.InitAndEnableFeature(
22348 features::kPartitionConnectionsByNetworkIsolationKey);
22349 } else {
22350 feature_list.InitAndDisableFeature(
22351 features::kPartitionConnectionsByNetworkIsolationKey);
22352 }
22353
22354 std::unique_ptr<HttpNetworkSession> session(
22355 CreateSession(&session_deps_));
22356
22357 // Reads and writes for the unpartitioned case, where only one socket is
22358 // used.
22359
22360 SpdyTestUtil spdy_util;
22361 spdy::SpdySerializedFrame unpartitioned_req1(
22362 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
22363 spdy::SpdySerializedFrame unpartitioned_response1(
22364 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
22365 spdy::SpdySerializedFrame unpartitioned_body1(
22366 spdy_util.ConstructSpdyDataFrame(1, "1", true));
22367 spdy_util.UpdateWithStreamDestruction(1);
22368
22369 spdy::SpdySerializedFrame unpartitioned_req2(
22370 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
22371 spdy::SpdySerializedFrame unpartitioned_response2(
22372 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
22373 spdy::SpdySerializedFrame unpartitioned_body2(
22374 spdy_util.ConstructSpdyDataFrame(3, "2", true));
22375 spdy_util.UpdateWithStreamDestruction(3);
22376
22377 spdy::SpdySerializedFrame unpartitioned_req3(
22378 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
22379 spdy::SpdySerializedFrame unpartitioned_response3(
22380 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
22381 spdy::SpdySerializedFrame unpartitioned_body3(
22382 spdy_util.ConstructSpdyDataFrame(5, "3", true));
22383
22384 const MockWrite kUnpartitionedWrites[] = {
22385 CreateMockWrite(unpartitioned_req1, 0),
22386 CreateMockWrite(unpartitioned_req2, 3),
22387 CreateMockWrite(unpartitioned_req3, 6),
22388 };
22389
22390 const MockRead kUnpartitionedReads[] = {
22391 CreateMockRead(unpartitioned_response1, 1),
22392 CreateMockRead(unpartitioned_body1, 2),
22393 CreateMockRead(unpartitioned_response2, 4),
22394 CreateMockRead(unpartitioned_body2, 5),
22395 CreateMockRead(unpartitioned_response3, 7),
22396 CreateMockRead(unpartitioned_body3, 8),
22397 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
22398 };
22399
22400 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
22401 kUnpartitionedWrites);
22402
22403 // Reads and writes for the partitioned case, where two sockets are used.
22404
22405 SpdyTestUtil spdy_util2;
22406 spdy::SpdySerializedFrame partitioned_req1(
22407 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22408 spdy::SpdySerializedFrame partitioned_response1(
22409 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22410 spdy::SpdySerializedFrame partitioned_body1(
22411 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22412 spdy_util2.UpdateWithStreamDestruction(1);
22413
22414 spdy::SpdySerializedFrame partitioned_req3(
22415 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22416 spdy::SpdySerializedFrame partitioned_response3(
22417 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22418 spdy::SpdySerializedFrame partitioned_body3(
22419 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22420
22421 const MockWrite kPartitionedWrites1[] = {
22422 CreateMockWrite(partitioned_req1, 0),
22423 CreateMockWrite(partitioned_req3, 3),
22424 };
22425
22426 const MockRead kPartitionedReads1[] = {
22427 CreateMockRead(partitioned_response1, 1),
22428 CreateMockRead(partitioned_body1, 2),
22429 CreateMockRead(partitioned_response3, 4),
22430 CreateMockRead(partitioned_body3, 5),
22431 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22432 };
22433
22434 SpdyTestUtil spdy_util3;
22435 spdy::SpdySerializedFrame partitioned_req2(
22436 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22437 spdy::SpdySerializedFrame partitioned_response2(
22438 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22439 spdy::SpdySerializedFrame partitioned_body2(
22440 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22441
22442 const MockWrite kPartitionedWrites2[] = {
22443 CreateMockWrite(partitioned_req2, 0),
22444 };
22445
22446 const MockRead kPartitionedReads2[] = {
22447 CreateMockRead(partitioned_response2, 1),
22448 CreateMockRead(partitioned_body2, 2),
22449 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22450 };
22451
22452 SequencedSocketData partitioned_data1(kPartitionedReads1,
22453 kPartitionedWrites1);
22454 SequencedSocketData partitioned_data2(kPartitionedReads2,
22455 kPartitionedWrites2);
22456
22457 // No need to segment SSLDataProviders by whether or not partitioning is
22458 // enabled.
22459 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22460 ssl_data1.next_proto = kProtoHTTP2;
22461 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22462 ssl_data2.next_proto = kProtoHTTP2;
22463
22464 if (partition_connections) {
22465 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22467 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22469 } else {
22470 session_deps_.socket_factory->AddSocketDataProvider(
22471 &unpartitioned_data);
22472 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22473 }
22474
22475 TestCompletionCallback callback;
22476 HttpRequestInfo request1;
22477 request1.method = "GET";
22478 request1.url = GURL(url1);
22479 request1.traffic_annotation =
22480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22481 request1.network_isolation_key = network_isolation_key1;
22482 auto trans1 =
22483 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22484 int rv =
22485 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22486 EXPECT_THAT(callback.GetResult(rv), IsOk());
22487 std::string response_data1;
22488 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22489 EXPECT_EQ("1", response_data1);
22490 trans1.reset();
22491
22492 HttpRequestInfo request2;
22493 request2.method = "GET";
22494 request2.url = GURL(url2);
22495 request2.traffic_annotation =
22496 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22497 request2.network_isolation_key = network_isolation_key2;
22498 auto trans2 =
22499 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22500 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22501 EXPECT_THAT(callback.GetResult(rv), IsOk());
22502 std::string response_data2;
22503 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22504 EXPECT_EQ("2", response_data2);
22505 trans2.reset();
22506
22507 HttpRequestInfo request3;
22508 request3.method = "GET";
22509 request3.url = GURL(url3);
22510 request3.traffic_annotation =
22511 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22512 request3.network_isolation_key = network_isolation_key1;
22513 auto trans3 =
22514 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22515 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22516 EXPECT_THAT(callback.GetResult(rv), IsOk());
22517 std::string response_data3;
22518 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22519 EXPECT_EQ("3", response_data3);
22520 trans3.reset();
22521 }
22522 }
22523}
22524
Matt Menke7281f872019-06-25 19:29:2522525// Preconnect two sockets with different NetworkIsolationKeys when
22526// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22527// request and make sure the correct socket is used. Loops three times,
22528// expecting to use the first preconnect, second preconnect, and neither.
22529TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22530 base::test::ScopedFeatureList feature_list;
22531 feature_list.InitAndEnableFeature(
22532 features::kPartitionConnectionsByNetworkIsolationKey);
22533
22534 enum class TestCase {
22535 kUseFirstPreconnect,
22536 kUseSecondPreconnect,
22537 kDontUsePreconnect,
22538 };
22539
Matt Menke4807a9a2020-11-21 00:14:4122540 const SchemefulSite kSite1(GURL("http://origin1/"));
22541 const SchemefulSite kSite2(GURL("http://origin2/"));
22542 const SchemefulSite kSite3(GURL("http://origin3/"));
22543 NetworkIsolationKey preconnect1_isolation_key(kSite1, kSite1);
22544 NetworkIsolationKey preconnect2_isolation_key(kSite2, kSite2);
22545 NetworkIsolationKey not_preconnected_isolation_key(kSite3, kSite3);
Matt Menke7281f872019-06-25 19:29:2522546
22547 // Test that only preconnects with
22548 for (TestCase test_case :
22549 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22550 TestCase::kDontUsePreconnect}) {
22551 SpdySessionDependencies session_deps;
22552 // Make DNS lookups completely synchronously, so preconnects complete
22553 // immediately.
22554 session_deps.host_resolver->set_synchronous_mode(true);
22555
22556 const MockWrite kMockWrites[] = {
22557 MockWrite(ASYNC, 0,
22558 "GET / HTTP/1.1\r\n"
22559 "Host: www.foo.com\r\n"
22560 "Connection: keep-alive\r\n\r\n"),
22561 };
22562
22563 const MockRead kMockReads[] = {
22564 MockRead(ASYNC, 1,
22565 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22566 "hello"),
22567 };
22568
22569 // Used for the socket that will actually be used, which may or may not be
22570 // one of the preconnects
22571 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22572 kMockReads, kMockWrites);
22573
22574 // Used for the preconnects that won't actually be used.
22575 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22576 base::span<const MockRead>(),
22577 base::span<const MockWrite>());
22578 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22579 base::span<const MockRead>(),
22580 base::span<const MockWrite>());
22581
22582 NetworkIsolationKey network_isolation_key_for_request;
22583
22584 switch (test_case) {
22585 case TestCase::kUseFirstPreconnect:
22586 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22587 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22588 network_isolation_key_for_request = preconnect1_isolation_key;
22589 break;
22590 case TestCase::kUseSecondPreconnect:
22591 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22592 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22593 network_isolation_key_for_request = preconnect2_isolation_key;
22594 break;
22595 case TestCase::kDontUsePreconnect:
22596 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22597 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22598 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22599 network_isolation_key_for_request = not_preconnected_isolation_key;
22600 break;
22601 }
22602
22603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22604
22605 // Preconnect sockets.
22606 HttpRequestInfo request;
22607 request.method = "GET";
22608 request.url = GURL("http://www.foo.com/");
22609 request.traffic_annotation =
22610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22611
22612 request.network_isolation_key = preconnect1_isolation_key;
22613 session->http_stream_factory()->PreconnectStreams(1, request);
22614
22615 request.network_isolation_key = preconnect2_isolation_key;
22616 session->http_stream_factory()->PreconnectStreams(1, request);
22617
22618 request.network_isolation_key = network_isolation_key_for_request;
22619
22620 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22621
22622 // Make the request.
22623 TestCompletionCallback callback;
22624
22625 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22626
22627 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22628 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22629
22630 rv = callback.WaitForResult();
22631 EXPECT_THAT(rv, IsOk());
22632
22633 const HttpResponseInfo* response = trans.GetResponseInfo();
22634 ASSERT_TRUE(response);
22635 ASSERT_TRUE(response->headers);
22636 EXPECT_EQ(200, response->headers->response_code());
22637
22638 std::string response_data;
22639 rv = ReadTransaction(&trans, &response_data);
22640 EXPECT_THAT(rv, IsOk());
22641 EXPECT_EQ("hello", response_data);
22642
22643 if (test_case != TestCase::kDontUsePreconnect) {
22644 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22645 } else {
22646 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22647 }
22648 }
22649}
22650
David Benjamin6f2da652019-06-26 23:36:3522651// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22652// cache is isolated.
22653TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22654 base::test::ScopedFeatureList feature_list;
22655 feature_list.InitWithFeatures(
22656 {features::kPartitionConnectionsByNetworkIsolationKey,
22657 features::kPartitionSSLSessionsByNetworkIsolationKey},
22658 {});
22659
Matt Menke4807a9a2020-11-21 00:14:4122660 const SchemefulSite kSite1(GURL("http://origin1/"));
22661 const SchemefulSite kSite2(GURL("http://origin2/"));
22662 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
22663 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
David Benjamin6f2da652019-06-26 23:36:3522664 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22665
22666 // The server always sends Connection: close, so each request goes over a
22667 // distinct socket.
22668
22669 const MockWrite kWrites1[] = {
22670 MockWrite("GET /1 HTTP/1.1\r\n"
22671 "Host: foo.test\r\n"
22672 "Connection: keep-alive\r\n\r\n")};
22673
22674 const MockRead kReads1[] = {
22675 MockRead("HTTP/1.1 200 OK\r\n"
22676 "Connection: close\r\n"
22677 "Content-Length: 1\r\n\r\n"
22678 "1")};
22679
22680 const MockWrite kWrites2[] = {
22681 MockWrite("GET /2 HTTP/1.1\r\n"
22682 "Host: foo.test\r\n"
22683 "Connection: keep-alive\r\n\r\n")};
22684
22685 const MockRead kReads2[] = {
22686 MockRead("HTTP/1.1 200 OK\r\n"
22687 "Connection: close\r\n"
22688 "Content-Length: 1\r\n\r\n"
22689 "2")};
22690
22691 const MockWrite kWrites3[] = {
22692 MockWrite("GET /3 HTTP/1.1\r\n"
22693 "Host: foo.test\r\n"
22694 "Connection: keep-alive\r\n\r\n")};
22695
22696 const MockRead kReads3[] = {
22697 MockRead("HTTP/1.1 200 OK\r\n"
22698 "Connection: close\r\n"
22699 "Content-Length: 1\r\n\r\n"
22700 "3")};
22701
22702 StaticSocketDataProvider data1(kReads1, kWrites1);
22703 StaticSocketDataProvider data2(kReads2, kWrites2);
22704 StaticSocketDataProvider data3(kReads3, kWrites3);
22705 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22706 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22707 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22708
22709 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22710 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22711 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22712 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22713 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22714 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22715 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22716 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22717 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22720 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22721
22722 TestCompletionCallback callback;
22723 HttpRequestInfo request1;
22724 request1.method = "GET";
22725 request1.url = GURL("https://foo.test/1");
22726 request1.traffic_annotation =
22727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22728 request1.network_isolation_key = kNetworkIsolationKey1;
22729 auto trans1 =
22730 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22731 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22732 EXPECT_THAT(callback.GetResult(rv), IsOk());
22733 std::string response_data1;
22734 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22735 EXPECT_EQ("1", response_data1);
22736 trans1.reset();
22737
22738 HttpRequestInfo request2;
22739 request2.method = "GET";
22740 request2.url = GURL("https://foo.test/2");
22741 request2.traffic_annotation =
22742 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22743 request2.network_isolation_key = kNetworkIsolationKey2;
22744 auto trans2 =
22745 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22746 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22747 EXPECT_THAT(callback.GetResult(rv), IsOk());
22748 std::string response_data2;
22749 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22750 EXPECT_EQ("2", response_data2);
22751 trans2.reset();
22752
22753 HttpRequestInfo request3;
22754 request3.method = "GET";
22755 request3.url = GURL("https://foo.test/3");
22756 request3.traffic_annotation =
22757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22758 request3.network_isolation_key = kNetworkIsolationKey1;
22759 auto trans3 =
22760 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22761 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22762 EXPECT_THAT(callback.GetResult(rv), IsOk());
22763 std::string response_data3;
22764 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22765 EXPECT_EQ("3", response_data3);
22766 trans3.reset();
22767}
22768
22769// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22770// cache is isolated, for both origins and proxies.
22771TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22772 base::test::ScopedFeatureList feature_list;
22773 feature_list.InitWithFeatures(
22774 {features::kPartitionConnectionsByNetworkIsolationKey,
22775 features::kPartitionSSLSessionsByNetworkIsolationKey},
22776 {});
22777
Nicolas Arciniegad2013f92020-02-07 23:00:5622778 session_deps_.proxy_resolution_service =
22779 ConfiguredProxyResolutionService::CreateFixed(
22780 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin6f2da652019-06-26 23:36:3522781
Matt Menke4807a9a2020-11-21 00:14:4122782 const SchemefulSite kSite1(GURL("http://origin1/"));
22783 const SchemefulSite kSite2(GURL("http://origin2/"));
22784 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
22785 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
David Benjamin6f2da652019-06-26 23:36:3522786 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22787
22788 // Make both a tunneled and non-tunneled request.
22789 HttpRequestInfo request1;
22790 request1.method = "GET";
22791 request1.url = GURL("https://foo.test/1");
22792 request1.traffic_annotation =
22793 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22794 request1.network_isolation_key = kNetworkIsolationKey1;
22795
22796 HttpRequestInfo request2;
22797 request2.method = "GET";
22798 request2.url = GURL("http://foo.test/2");
22799 request2.traffic_annotation =
22800 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22801 request2.network_isolation_key = kNetworkIsolationKey2;
22802
22803 const MockWrite kWrites1[] = {
22804 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22805 "Host: foo.test:443\r\n"
22806 "Proxy-Connection: keep-alive\r\n\r\n"),
22807 MockWrite("GET /1 HTTP/1.1\r\n"
22808 "Host: foo.test\r\n"
22809 "Connection: keep-alive\r\n\r\n")};
22810
22811 const MockRead kReads1[] = {
22812 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22813 MockRead("HTTP/1.1 200 OK\r\n"
22814 "Connection: close\r\n"
22815 "Content-Length: 1\r\n\r\n"
22816 "1")};
22817
22818 const MockWrite kWrites2[] = {
22819 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22820 "Host: foo.test\r\n"
22821 "Proxy-Connection: keep-alive\r\n\r\n")};
22822
22823 const MockRead kReads2[] = {
22824 MockRead("HTTP/1.1 200 OK\r\n"
22825 "Connection: close\r\n"
22826 "Content-Length: 1\r\n\r\n"
22827 "2")};
22828
22829 StaticSocketDataProvider data1(kReads1, kWrites1);
22830 StaticSocketDataProvider data2(kReads2, kWrites2);
22831 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22832 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22833 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22834
22835 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22836 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22837 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22838 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22839 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22840 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22841 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22842 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22843 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22845 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22847
22848 TestCompletionCallback callback;
22849 auto trans1 =
22850 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22851 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22852 EXPECT_THAT(callback.GetResult(rv), IsOk());
22853 std::string response_data1;
22854 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22855 EXPECT_EQ("1", response_data1);
22856 trans1.reset();
22857
22858 auto trans2 =
22859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22860 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22861 EXPECT_THAT(callback.GetResult(rv), IsOk());
22862 std::string response_data2;
22863 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22864 EXPECT_EQ("2", response_data2);
22865 trans2.reset();
22866}
22867
David Benjaminef2f2a5a2019-07-16 19:21:3122868// Test that SSLConfig changes from SSLConfigService are picked up even when
22869// there are live sockets.
22870TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222871 SSLContextConfig ssl_context_config;
22872 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22873 auto ssl_config_service =
22874 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122875 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22876
22877 session_deps_.ssl_config_service = std::move(ssl_config_service);
22878
22879 // Make three requests. Between the second and third, the SSL config will
22880 // change.
22881 HttpRequestInfo request1;
22882 request1.method = "GET";
22883 request1.url = GURL("https://foo.test/1");
22884 request1.traffic_annotation =
22885 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22886
22887 HttpRequestInfo request2;
22888 request2.method = "GET";
22889 request2.url = GURL("https://foo.test/2");
22890 request2.traffic_annotation =
22891 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22892
22893 HttpRequestInfo request3;
22894 request3.method = "GET";
22895 request3.url = GURL("https://foo.test/3");
22896 request3.traffic_annotation =
22897 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22898
22899 const MockWrite kWrites1[] = {
22900 MockWrite("GET /1 HTTP/1.1\r\n"
22901 "Host: foo.test\r\n"
22902 "Connection: keep-alive\r\n\r\n"),
22903 MockWrite("GET /2 HTTP/1.1\r\n"
22904 "Host: foo.test\r\n"
22905 "Connection: keep-alive\r\n\r\n"),
22906 };
22907
22908 const MockRead kReads1[] = {
22909 MockRead("HTTP/1.1 200 OK\r\n"
22910 "Connection: keep-alive\r\n"
22911 "Content-Length: 1\r\n\r\n"
22912 "1"),
22913 MockRead("HTTP/1.1 200 OK\r\n"
22914 "Connection: keep-alive\r\n"
22915 "Content-Length: 1\r\n\r\n"
22916 "2"),
22917 };
22918
22919 // The third request goes on a different socket because the SSL config has
22920 // changed.
22921 const MockWrite kWrites2[] = {
22922 MockWrite("GET /3 HTTP/1.1\r\n"
22923 "Host: foo.test\r\n"
22924 "Connection: keep-alive\r\n\r\n")};
22925
22926 const MockRead kReads2[] = {
22927 MockRead("HTTP/1.1 200 OK\r\n"
22928 "Connection: keep-alive\r\n"
22929 "Content-Length: 1\r\n\r\n"
22930 "3")};
22931
22932 StaticSocketDataProvider data1(kReads1, kWrites1);
22933 StaticSocketDataProvider data2(kReads2, kWrites2);
22934 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22935 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22936
22937 SSLSocketDataProvider ssl1(ASYNC, OK);
22938 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22939 SSLSocketDataProvider ssl2(ASYNC, OK);
22940 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22941 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22942 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22943
22944 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22945
22946 TestCompletionCallback callback;
22947 auto trans1 =
22948 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22949 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22950 EXPECT_THAT(callback.GetResult(rv), IsOk());
22951 std::string response_data1;
22952 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22953 EXPECT_EQ("1", response_data1);
22954 trans1.reset();
22955
22956 auto trans2 =
22957 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22958 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22959 EXPECT_THAT(callback.GetResult(rv), IsOk());
22960 std::string response_data2;
22961 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22962 EXPECT_EQ("2", response_data2);
22963 trans2.reset();
22964
David Benjamin151ec6b2019-08-02 19:38:5222965 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22966 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122967
22968 auto trans3 =
22969 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22970 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22971 EXPECT_THAT(callback.GetResult(rv), IsOk());
22972 std::string response_data3;
22973 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22974 EXPECT_EQ("3", response_data3);
22975 trans3.reset();
22976}
22977
22978TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222979 SSLContextConfig ssl_context_config;
22980 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22981 auto ssl_config_service =
22982 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122983 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22984
22985 session_deps_.ssl_config_service = std::move(ssl_config_service);
22986
22987 HttpRequestInfo request;
22988 request.method = "GET";
22989 request.url = GURL("https://foo.test/1");
22990 request.traffic_annotation =
22991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22992
22993 // Make a socket which never connects.
22994 StaticSocketDataProvider data({}, {});
22995 session_deps_.socket_factory->AddSocketDataProvider(&data);
22996 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22997 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22998 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22999
23000 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23001
23002 TestCompletionCallback callback;
23003 auto trans =
23004 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23005 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
23006 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23007
David Benjamin151ec6b2019-08-02 19:38:5223008 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
23009 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3123010
23011 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
23012}
23013
David Benjaminbac8dff2019-08-07 01:30:4123014// Test that HttpNetworkTransaction correctly handles existing sockets when the
23015// server requests a client certificate post-handshake (via a TLS
23016// renegotiation). This is a regression test for https://crbug.com/829184.
23017TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
23018 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
23019 TRAFFIC_ANNOTATION_FOR_TESTS);
23020
23021 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
23022 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
23023
23024 std::unique_ptr<FakeClientCertIdentity> identity =
23025 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
23026 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
23027 ASSERT_TRUE(identity);
23028
23029 // This test will make several requests so that, when the client certificate
23030 // request comes in, we have a socket in use, an idle socket, and a socket for
23031 // an unrelated host.
23032 //
23033 // First, two long-lived requests which do not complete until after the client
23034 // certificate request. This arranges for sockets to be in use during the
23035 // request. They should not be interrupted.
23036 HttpRequestInfo request_long_lived;
23037 request_long_lived.method = "GET";
23038 request_long_lived.url = GURL("https://foo.test/long-lived");
23039 request_long_lived.traffic_annotation = kTrafficAnnotation;
23040
23041 HttpRequestInfo request_long_lived_bar;
23042 request_long_lived_bar.method = "GET";
23043 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
23044 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
23045
23046 // Next, make a request that needs client certificates.
23047 HttpRequestInfo request_auth;
23048 request_auth.method = "GET";
23049 request_auth.url = GURL("https://foo.test/auth");
23050 request_auth.traffic_annotation = kTrafficAnnotation;
23051
23052 // Before responding to the challenge, make a request to an unauthenticated
23053 // endpoint. This will result in an idle socket when the client certificate
23054 // challenge is resolved.
23055 HttpRequestInfo request_unauth;
23056 request_unauth.method = "GET";
23057 request_unauth.url = GURL("https://foo.test/unauth");
23058 request_unauth.traffic_annotation = kTrafficAnnotation;
23059
23060 // After all the preceding requests complete, end with two additional requests
23061 // to ensure pre-authentication foo.test sockets are not used and bar.test
23062 // sockets are unaffected.
23063 HttpRequestInfo request_post_auth;
23064 request_post_auth.method = "GET";
23065 request_post_auth.url = GURL("https://foo.test/post-auth");
23066 request_post_auth.traffic_annotation = kTrafficAnnotation;
23067
23068 HttpRequestInfo request_post_auth_bar;
23069 request_post_auth_bar.method = "GET";
23070 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
23071 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
23072
23073 // The sockets for /long-lived and /unauth complete their request but are
23074 // not allocated for /post-auth or /retry because SSL state has since changed.
23075 const MockWrite kLongLivedWrites[] = {
23076 MockWrite(ASYNC, 0,
23077 "GET /long-lived HTTP/1.1\r\n"
23078 "Host: foo.test\r\n"
23079 "Connection: keep-alive\r\n\r\n"),
23080 };
23081 const MockRead kLongLivedReads[] = {
23082 // Pause so /long-lived completes after the client presents client
23083 // certificates.
23084 MockRead(ASYNC, ERR_IO_PENDING, 1),
23085 MockRead(ASYNC, 2,
23086 "HTTP/1.1 200 OK\r\n"
23087 "Connection: keep-alive\r\n"
23088 "Content-Length: 10\r\n\r\n"
23089 "long-lived"),
23090 };
23091 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
23092 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
23093 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
23094 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
23095
23096 // Requests for bar.test should be unaffected by foo.test and get allocated
23097 // a single socket.
23098 const MockWrite kBarWrites[] = {
23099 MockWrite(ASYNC, 0,
23100 "GET /long-lived HTTP/1.1\r\n"
23101 "Host: bar.test\r\n"
23102 "Connection: keep-alive\r\n\r\n"),
23103 MockWrite(ASYNC, 3,
23104 "GET /post-auth HTTP/1.1\r\n"
23105 "Host: bar.test\r\n"
23106 "Connection: keep-alive\r\n\r\n"),
23107 };
23108 const MockRead kBarReads[] = {
23109 // Pause on /long-lived so it completes after foo.test's authentication.
23110 MockRead(ASYNC, ERR_IO_PENDING, 1),
23111 MockRead(ASYNC, 2,
23112 "HTTP/1.1 200 OK\r\n"
23113 "Connection: keep-alive\r\n"
23114 "Content-Length: 10\r\n\r\n"
23115 "long-lived"),
23116 MockRead(ASYNC, 4,
23117 "HTTP/1.1 200 OK\r\n"
23118 "Connection: keep-alive\r\n"
23119 "Content-Length: 9\r\n\r\n"
23120 "post-auth"),
23121 };
23122 SequencedSocketData data_bar(kBarReads, kBarWrites);
23123 SSLSocketDataProvider ssl_bar(ASYNC, OK);
23124 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
23125 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
23126
23127 // Requesting /auth results in a post-handshake client certificate challenge.
23128 const MockWrite kAuthWrites[] = {
23129 MockWrite(ASYNC, 0,
23130 "GET /auth HTTP/1.1\r\n"
23131 "Host: foo.test\r\n"
23132 "Connection: keep-alive\r\n\r\n"),
23133 };
23134 const MockRead kAuthReads[] = {
23135 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
23136 };
23137 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
23138 SSLSocketDataProvider ssl_auth(ASYNC, OK);
23139 ssl_auth.cert_request_info = cert_request_info.get();
23140 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
23141 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
23142
23143 // Requesting /unauth completes.
23144 const MockWrite kUnauthWrites[] = {
23145 MockWrite(ASYNC, 0,
23146 "GET /unauth HTTP/1.1\r\n"
23147 "Host: foo.test\r\n"
23148 "Connection: keep-alive\r\n\r\n"),
23149 };
23150 const MockRead kUnauthReads[] = {
23151 MockRead(ASYNC, 1,
23152 "HTTP/1.1 200 OK\r\n"
23153 "Connection: keep-alive\r\n"
23154 "Content-Length: 6\r\n\r\n"
23155 "unauth"),
23156 };
23157 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
23158 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
23159 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
23160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
23161
23162 // When the client certificate is selected, /auth is retried on a new
23163 // connection. In particular, it should not be retried on |data_unauth|,
23164 // which would not honor the new client certificate configuration.
23165 const MockWrite kRetryWrites[] = {
23166 MockWrite(ASYNC, 0,
23167 "GET /auth HTTP/1.1\r\n"
23168 "Host: foo.test\r\n"
23169 "Connection: keep-alive\r\n\r\n"),
23170 };
23171 const MockRead kRetryReads[] = {
23172 MockRead(ASYNC, 1,
23173 "HTTP/1.1 200 OK\r\n"
23174 // Close the connection so we test that /post-auth is not
23175 // allocated to |data_unauth| or |data_long_lived|.
23176 "Connection: close\r\n"
23177 "Content-Length: 4\r\n\r\n"
23178 "auth"),
23179 };
23180 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
23181 SSLSocketDataProvider ssl_retry(ASYNC, OK);
23182 ssl_retry.expected_send_client_cert = true;
23183 ssl_retry.expected_client_cert = identity->certificate();
23184 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
23185 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
23186
23187 // /post-auth gets its own socket.
23188 const MockWrite kPostAuthWrites[] = {
23189 MockWrite(ASYNC, 0,
23190 "GET /post-auth HTTP/1.1\r\n"
23191 "Host: foo.test\r\n"
23192 "Connection: keep-alive\r\n\r\n"),
23193 };
23194 const MockRead kPostAuthReads[] = {
23195 MockRead(ASYNC, 1,
23196 "HTTP/1.1 200 OK\r\n"
23197 "Connection: keep-alive\r\n"
23198 "Content-Length: 9\r\n\r\n"
23199 "post-auth"),
23200 };
23201 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
23202 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
23203 ssl_post_auth.expected_send_client_cert = true;
23204 ssl_post_auth.expected_client_cert = identity->certificate();
23205 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
23206 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
23207
23208 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23209
23210 // Start the two long-lived requests.
23211 TestCompletionCallback callback_long_lived;
23212 auto trans_long_lived =
23213 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23214 int rv = trans_long_lived->Start(
23215 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
23216 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23217 data_long_lived.RunUntilPaused();
23218
23219 TestCompletionCallback callback_long_lived_bar;
23220 auto trans_long_lived_bar =
23221 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23222 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
23223 callback_long_lived_bar.callback(),
23224 NetLogWithSource());
23225 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23226 data_bar.RunUntilPaused();
23227
23228 // Request /auth. This gives a client certificate challenge.
23229 TestCompletionCallback callback_auth;
23230 auto trans_auth =
23231 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23232 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
23233 NetLogWithSource());
23234 EXPECT_THAT(callback_auth.GetResult(rv),
23235 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
23236
23237 // Make an unauthenticated request. This completes.
23238 TestCompletionCallback callback_unauth;
23239 auto trans_unauth =
23240 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23241 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
23242 NetLogWithSource());
23243 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
23244 std::string response_unauth;
23245 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
23246 EXPECT_EQ("unauth", response_unauth);
23247 trans_unauth.reset();
23248
23249 // Complete the authenticated request.
23250 rv = trans_auth->RestartWithCertificate(identity->certificate(),
23251 identity->ssl_private_key(),
23252 callback_auth.callback());
23253 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
23254 std::string response_auth;
23255 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
23256 EXPECT_EQ("auth", response_auth);
23257 trans_auth.reset();
23258
23259 // Complete the long-lived requests.
23260 data_long_lived.Resume();
23261 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
23262 std::string response_long_lived;
23263 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
23264 IsOk());
23265 EXPECT_EQ("long-lived", response_long_lived);
23266 trans_long_lived.reset();
23267
23268 data_bar.Resume();
23269 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
23270 std::string response_long_lived_bar;
23271 EXPECT_THAT(
23272 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
23273 IsOk());
23274 EXPECT_EQ("long-lived", response_long_lived_bar);
23275 trans_long_lived_bar.reset();
23276
23277 // Run the post-authentication requests.
23278 TestCompletionCallback callback_post_auth;
23279 auto trans_post_auth =
23280 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23281 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
23282 NetLogWithSource());
23283 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
23284 std::string response_post_auth;
23285 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
23286 IsOk());
23287 EXPECT_EQ("post-auth", response_post_auth);
23288 trans_post_auth.reset();
23289
23290 TestCompletionCallback callback_post_auth_bar;
23291 auto trans_post_auth_bar =
23292 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23293 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
23294 callback_post_auth_bar.callback(),
23295 NetLogWithSource());
23296 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
23297 std::string response_post_auth_bar;
23298 EXPECT_THAT(
23299 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
23300 IsOk());
23301 EXPECT_EQ("post-auth", response_post_auth_bar);
23302 trans_post_auth_bar.reset();
23303}
23304
[email protected]89ceba9a2009-03-21 03:46:0623305} // namespace net