blob: 9d6ad72252b1064cda399c2edc0966d518bc6631 [file] [log] [blame]
[email protected]23e482282013-06-14 16:08:021// Copyright 2013 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
sclittlebe1ccf62015-09-02 19:40:369#include <stdint.h>
danakj1fd259a02016-04-16 03:17:0910
avibf0746c2015-12-09 19:53:1411#include <limits>
rdsmith1d343be52016-10-21 20:37:5012#include <set>
[email protected]5285d972011-10-18 18:56:3413#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3315#include <vector>
[email protected]77848d12008-11-14 00:00:2216
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]68bf9152008-09-25 19:47:3018#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5219#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2920#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5721#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2422#include "base/logging.h"
danakj1fd259a02016-04-16 03:17:0923#include "base/memory/ptr_util.h"
[email protected]bf828982013-08-14 18:01:4724#include "base/memory/weak_ptr.h"
Eric Orthf4db66a2019-02-19 21:35:3325#include "base/optional.h"
[email protected]a34f61ee2014-03-18 20:59:4926#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2427#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1928#include "base/strings/string_piece.h"
[email protected]125ef482013-06-11 18:32:4729#include "base/strings/string_util.h"
Matt Menked732ea42019-03-08 12:05:0030#include "base/strings/stringprintf.h"
[email protected]750b2f3c2013-06-07 18:41:0531#include "base/strings/utf_string_conversions.h"
Douglas Creager3cb042052018-11-06 23:08:5232#include "base/test/metrics/histogram_tester.h"
Matt Menke166443c2019-05-24 18:45:5933#include "base/test/scoped_feature_list.h"
Douglas Creager134b52e2018-11-09 18:00:1434#include "base/test/simple_test_clock.h"
35#include "base/test/simple_test_tick_clock.h"
Gabriel Charettec7108742019-08-23 03:31:4036#include "base/test/task_environment.h"
[email protected]f36a8132011-09-02 18:36:3337#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3538#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2439#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3540#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3942#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0743#include "net/base/elements_upload_data_stream.h"
Matt Menke166443c2019-05-24 18:45:5944#include "net/base/features.h"
Eric Orthf4db66a2019-02-19 21:35:3345#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3746#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2547#include "net/base/load_timing_info.h"
48#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2449#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5950#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1551#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4052#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3153#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1555#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0656#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2157#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0858#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1159#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5360#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2461#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1262#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0063#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2964#include "net/http/http_auth_handler_ntlm.h"
Asanka Herathbf0b55d2019-12-07 03:27:0965#include "net/http/http_auth_ntlm_mechanism.h"
aberentbba302d2015-12-03 10:20:1966#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5767#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5268#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5669#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0470#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2471#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1372#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2673#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5774#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3875#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1976#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0777#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0078#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1979#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5180#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4681#include "net/log/test_net_log_util.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5682#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4083#include "net/proxy_resolution/mock_proxy_resolver.h"
84#include "net/proxy_resolution/proxy_config_service_fixed.h"
85#include "net/proxy_resolution/proxy_info.h"
86#include "net/proxy_resolution/proxy_resolver.h"
87#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4488#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1589#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0390#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3691#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4792#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0293#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0794#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0495#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4496#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1297#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4498#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5899#include "net/spdy/spdy_session.h"
100#include "net/spdy/spdy_session_pool.h"
101#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04102#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57103#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31104#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03105#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57106#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54107#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52108#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11109#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01110#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43111#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:40112#include "net/test/test_with_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14113#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23114#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00115#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44116#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06117#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18118#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52119#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15120#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27121#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52122
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37123#if defined(NTLM_PORTABLE)
124#include "base/base64.h"
125#include "net/ntlm/ntlm_test_data.h"
126#endif
127
Douglas Creager3cb042052018-11-06 23:08:52128#if BUILDFLAG(ENABLE_REPORTING)
129#include "net/network_error_logging/network_error_logging_service.h"
130#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14131#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10132#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14133#include "net/reporting/reporting_header_parser.h"
134#include "net/reporting/reporting_service.h"
135#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52136#endif // BUILDFLAG(ENABLE_REPORTING)
137
robpercival214763f2016-07-01 23:27:01138using net::test::IsError;
139using net::test::IsOk;
140
[email protected]ad65a3e2013-12-25 18:18:01141using base::ASCIIToUTF16;
142
David Benjamin3b94b0f2019-04-25 23:07:52143using testing::AnyOf;
144
initial.commit586acc5fe2008-07-26 22:42:52145//-----------------------------------------------------------------------------
146
ttuttle859dc7a2015-04-23 19:42:29147namespace net {
148
[email protected]13c8a092010-07-29 06:15:44149namespace {
150
[email protected]42cba2fb2013-03-29 19:58:57151const base::string16 kBar(ASCIIToUTF16("bar"));
152const base::string16 kBar2(ASCIIToUTF16("bar2"));
153const base::string16 kBar3(ASCIIToUTF16("bar3"));
154const base::string16 kBaz(ASCIIToUTF16("baz"));
155const base::string16 kFirst(ASCIIToUTF16("first"));
156const base::string16 kFoo(ASCIIToUTF16("foo"));
157const base::string16 kFoo2(ASCIIToUTF16("foo2"));
158const base::string16 kFoo3(ASCIIToUTF16("foo3"));
159const base::string16 kFou(ASCIIToUTF16("fou"));
160const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57161const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44162
bnc2df4b522016-07-08 18:17:43163const char kAlternativeServiceHttpHeader[] =
164 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
165
ttuttle859dc7a2015-04-23 19:42:29166int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40167 return session
168 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
169 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29170 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02171}
172
ttuttle859dc7a2015-04-23 19:42:29173bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40174 return session
175 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
176 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29177 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52178}
179
[email protected]f3da152d2012-06-02 01:00:57180// Takes in a Value created from a NetLogHttpResponseParameter, and returns
181// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54182// of double quotes for easier comparison.
183std::string GetHeaders(const base::Value& params) {
184 if (!params.is_dict())
185 return "";
186 const base::Value* header_list = params.FindListKey("headers");
187 if (!header_list)
188 return "";
189 std::string headers;
190 base::JSONWriter::Write(*header_list, &headers);
191 base::ReplaceChars(headers, "\"", "'", &headers);
192 return headers;
[email protected]f3da152d2012-06-02 01:00:57193}
194
[email protected]029c83b62013-01-24 05:28:20195// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
196// used.
ttuttle859dc7a2015-04-23 19:42:29197void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20198 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19199 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25200
[email protected]029c83b62013-01-24 05:28:20201 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
202 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
203
ttuttle859dc7a2015-04-23 19:42:29204 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20205 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25206
207 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25208
[email protected]3b23a222013-05-15 21:33:25209 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25210 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
211 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25212 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25213}
214
[email protected]029c83b62013-01-24 05:28:20215// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
216// used.
ttuttle859dc7a2015-04-23 19:42:29217void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25218 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20219 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19220 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20221
222 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
223 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
224
ttuttle859dc7a2015-04-23 19:42:29225 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
226 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20227 EXPECT_LE(load_timing_info.connect_timing.connect_end,
228 load_timing_info.send_start);
229
230 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20231
[email protected]3b23a222013-05-15 21:33:25232 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20233 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
234 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25235 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20236}
237
238// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
239// used.
ttuttle859dc7a2015-04-23 19:42:29240void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20241 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19242 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20243
ttuttle859dc7a2015-04-23 19:42:29244 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20245
246 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
247 EXPECT_LE(load_timing_info.proxy_resolve_start,
248 load_timing_info.proxy_resolve_end);
249 EXPECT_LE(load_timing_info.proxy_resolve_end,
250 load_timing_info.send_start);
251 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20252
[email protected]3b23a222013-05-15 21:33:25253 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20254 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
255 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25256 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20257}
258
259// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
260// used.
ttuttle859dc7a2015-04-23 19:42:29261void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20262 int connect_timing_flags) {
263 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19264 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20265
266 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
267 EXPECT_LE(load_timing_info.proxy_resolve_start,
268 load_timing_info.proxy_resolve_end);
269 EXPECT_LE(load_timing_info.proxy_resolve_end,
270 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29271 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
272 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20273 EXPECT_LE(load_timing_info.connect_timing.connect_end,
274 load_timing_info.send_start);
275
276 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20277
[email protected]3b23a222013-05-15 21:33:25278 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20279 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
280 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25281 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25282}
283
Matt Menke2436b2f2018-12-11 18:07:11284// ProxyResolver that records URLs passed to it, and that can be told what
285// result to return.
286class CapturingProxyResolver : public ProxyResolver {
287 public:
Matt Menke8045afd2019-11-14 20:31:19288 struct LookupInfo {
289 GURL url;
290 NetworkIsolationKey network_isolation_key;
291 };
292
Matt Menke2436b2f2018-12-11 18:07:11293 CapturingProxyResolver()
294 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
295 ~CapturingProxyResolver() override = default;
296
297 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:39298 const NetworkIsolationKey& network_isolation_key,
Matt Menke2436b2f2018-12-11 18:07:11299 ProxyInfo* results,
300 CompletionOnceCallback callback,
301 std::unique_ptr<Request>* request,
302 const NetLogWithSource& net_log) override {
303 results->UseProxyServer(proxy_server_);
Matt Menke8045afd2019-11-14 20:31:19304 lookup_info_.push_back(LookupInfo{url, network_isolation_key});
Matt Menke2436b2f2018-12-11 18:07:11305 return OK;
306 }
307
308 // Sets whether the resolver should use direct connections, instead of a
309 // proxy.
310 void set_proxy_server(ProxyServer proxy_server) {
311 proxy_server_ = proxy_server;
312 }
313
Matt Menke8045afd2019-11-14 20:31:19314 const std::vector<LookupInfo>& lookup_info() const { return lookup_info_; }
Matt Menke2436b2f2018-12-11 18:07:11315
316 private:
Matt Menke8045afd2019-11-14 20:31:19317 std::vector<LookupInfo> lookup_info_;
Matt Menke2436b2f2018-12-11 18:07:11318
319 ProxyServer proxy_server_;
320
321 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
322};
323
324class CapturingProxyResolverFactory : public ProxyResolverFactory {
325 public:
326 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
327 : ProxyResolverFactory(false), resolver_(resolver) {}
328
329 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
330 std::unique_ptr<ProxyResolver>* resolver,
331 CompletionOnceCallback callback,
332 std::unique_ptr<Request>* request) override {
333 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
334 return OK;
335 }
336
337 private:
338 ProxyResolver* resolver_;
339};
340
danakj1fd259a02016-04-16 03:17:09341std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42342 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34343 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14344}
345
xunjieli96f2a402017-06-05 17:24:27346class FailingProxyResolverFactory : public ProxyResolverFactory {
347 public:
348 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
349
350 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42351 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
352 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17353 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42354 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27355 return ERR_PAC_SCRIPT_FAILED;
356 }
357};
358
[email protected]448d4ca52012-03-04 04:12:23359} // namespace
360
Bence Béky98447b12018-05-08 03:14:01361class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05362 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03363 public:
bncd16676a2016-07-20 16:23:01364 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03365 // Important to restore the per-pool limit first, since the pool limit must
366 // always be greater than group limit, and the tests reduce both limits.
367 ClientSocketPoolManager::set_max_sockets_per_pool(
368 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
369 ClientSocketPoolManager::set_max_sockets_per_group(
370 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
371 }
372
[email protected]e3ceb682011-06-28 23:55:46373 protected:
[email protected]23e482282013-06-14 16:08:02374 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05375 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36376 dummy_connect_job_params_(
377 nullptr /* client_socket_factory */,
378 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40379 nullptr /* http_auth_cache */,
380 nullptr /* http_auth_handler_factory */,
381 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13382 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40383 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36384 nullptr /* proxy_delegate */,
385 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18386 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36387 nullptr /* socket_performance_watcher_factory */,
388 nullptr /* network_quality_estimator */,
389 nullptr /* net_log */,
390 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56391 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15392 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03393 HttpNetworkSession::NORMAL_SOCKET_POOL)),
394 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
395 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28396 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03397 }
[email protected]bb88e1d32013-05-03 23:11:07398
[email protected]e3ceb682011-06-28 23:55:46399 struct SimpleGetHelperResult {
400 int rv;
401 std::string status_line;
402 std::string response_data;
sclittlefb249892015-09-10 21:33:22403 int64_t total_received_bytes;
404 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25405 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47406 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59407 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46408 };
409
dcheng67be2b1f2014-10-27 21:47:29410 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50411 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55412 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56413 // Set an initial delay to ensure that the first call to TimeTicks::Now()
414 // before incrementing the counter does not return a null value.
Matt Menke6dc08232019-10-03 18:00:28415 FastForwardBy(base::TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54416 }
417
dcheng67be2b1f2014-10-27 21:47:29418 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50419 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55420 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09421 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55422 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09423 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50424 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55425 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09426 }
427
Andrew Comminos1f2ff1cc2018-12-14 05:22:38428 void Check100ResponseTiming(bool use_spdy);
429
[email protected]202965992011-12-07 23:04:51430 // Either |write_failure| specifies a write failure or |read_failure|
431 // specifies a read failure when using a reused socket. In either case, the
432 // failure should cause the network transaction to resend the request, and the
433 // other argument should be NULL.
434 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
435 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52436
[email protected]a34f61ee2014-03-18 20:59:49437 // Either |write_failure| specifies a write failure or |read_failure|
438 // specifies a read failure when using a reused socket. In either case, the
439 // failure should cause the network transaction to resend the request, and the
440 // other argument should be NULL.
441 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10442 const MockRead* read_failure,
443 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49444
Ryan Sleevib8d7ea02018-05-07 20:01:01445 SimpleGetHelperResult SimpleGetHelperForData(
446 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15447 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52448
[email protected]ff007e162009-05-23 09:13:15449 HttpRequestInfo request;
450 request.method = "GET";
bncce36dca22015-04-21 22:11:23451 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10452 request.traffic_annotation =
453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52454
Matt Muellerd9342e3a2019-11-26 01:41:14455 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07456 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09457 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16458 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27459
Ryan Sleevib8d7ea02018-05-07 20:01:01460 for (auto* provider : providers) {
461 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29462 }
initial.commit586acc5fe2008-07-26 22:42:52463
[email protected]49639fa2011-12-20 23:22:41464 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52465
eroman24bc6a12015-05-06 19:55:48466 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16467 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01468 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52469
[email protected]ff007e162009-05-23 09:13:15470 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16471 out.total_received_bytes = trans.GetTotalReceivedBytes();
472 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25473
474 // Even in the failure cases that use this function, connections are always
475 // successfully established before the error.
bnc691fda62016-08-12 00:43:16476 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25477 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
478
[email protected]ff007e162009-05-23 09:13:15479 if (out.rv != OK)
480 return out;
481
bnc691fda62016-08-12 00:43:16482 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50483 // Can't use ASSERT_* inside helper functions like this, so
484 // return an error.
wezca1070932016-05-26 20:30:52485 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50486 out.rv = ERR_UNEXPECTED;
487 return out;
488 }
[email protected]ff007e162009-05-23 09:13:15489 out.status_line = response->headers->GetStatusLine();
490
Tsuyoshi Horo01faed62019-02-20 22:11:37491 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
492 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19493
ttuttled9dbc652015-09-29 20:00:59494 bool got_endpoint =
bnc691fda62016-08-12 00:43:16495 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59496 EXPECT_EQ(got_endpoint,
497 out.remote_endpoint_after_start.address().size() > 0);
498
bnc691fda62016-08-12 00:43:16499 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01500 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40501
Eric Roman79cc7552019-07-19 02:17:54502 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39503 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00504 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
505 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39506 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00507 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
508 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15509
Eric Roman79cc7552019-07-19 02:17:54510 EXPECT_EQ("GET / HTTP/1.1\r\n",
511 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57512
bncce36dca22015-04-21 22:11:23513 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54514 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40515
bnc691fda62016-08-12 00:43:16516 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22517 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16518 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22519
bnc691fda62016-08-12 00:43:16520 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47521 return out;
[email protected]ff007e162009-05-23 09:13:15522 }
initial.commit586acc5fe2008-07-26 22:42:52523
Ryan Sleevib8d7ea02018-05-07 20:01:01524 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22525 MockWrite data_writes[] = {
526 MockWrite("GET / HTTP/1.1\r\n"
527 "Host: www.example.org\r\n"
528 "Connection: keep-alive\r\n\r\n"),
529 };
[email protected]5a60c8b2011-10-19 20:14:29530
Ryan Sleevib8d7ea02018-05-07 20:01:01531 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22532 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01533 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22534
Ryan Sleevib8d7ea02018-05-07 20:01:01535 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22536 return out;
[email protected]b8015c42013-12-24 15:18:19537 }
538
bnc032658ba2016-09-26 18:17:15539 void AddSSLSocketData() {
540 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49541 ssl_.ssl_info.cert =
542 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
543 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15544 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
545 }
546
[email protected]ff007e162009-05-23 09:13:15547 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
548 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52549
[email protected]ff007e162009-05-23 09:13:15550 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07551
[email protected]bb88e1d32013-05-03 23:11:07552 void CheckErrorIsPassedBack(int error, IoMode mode);
553
David Benjaminbae08ba2019-10-18 21:06:15554 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
555 return base::BindRepeating(&HttpNetworkTransactionTest::FastForwardBy,
556 base::Unretained(this), delta);
557 }
558
Matt Menked6fd2a52019-03-20 06:14:36559 const CommonConnectJobParams dummy_connect_job_params_;
560
Douglas Creager134b52e2018-11-09 18:00:14561 // These clocks are defined here, even though they're only used in the
562 // Reporting tests below, since they need to be destroyed after
563 // |session_deps_|.
564 base::SimpleTestClock clock_;
565 base::SimpleTestTickClock tick_clock_;
566
[email protected]4bd46222013-05-14 19:32:23567 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07568 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15569 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03570
571 // Original socket limits. Some tests set these. Safest to always restore
572 // them once each test has been run.
573 int old_max_group_sockets_;
574 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15575};
[email protected]231d5a32008-09-13 00:45:27576
[email protected]448d4ca52012-03-04 04:12:23577namespace {
578
ryansturm49a8cb12016-06-15 16:51:09579class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27580 public:
ryansturm49a8cb12016-06-15 16:51:09581 BeforeHeadersSentHandler()
582 : observed_before_headers_sent_with_proxy_(false),
583 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27584
ryansturm49a8cb12016-06-15 16:51:09585 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
586 HttpRequestHeaders* request_headers) {
587 observed_before_headers_sent_ = true;
588 if (!proxy_info.is_http() && !proxy_info.is_https() &&
589 !proxy_info.is_quic()) {
590 return;
591 }
592 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27593 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
594 }
595
ryansturm49a8cb12016-06-15 16:51:09596 bool observed_before_headers_sent_with_proxy() const {
597 return observed_before_headers_sent_with_proxy_;
598 }
599
600 bool observed_before_headers_sent() const {
601 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27602 }
603
604 std::string observed_proxy_server_uri() const {
605 return observed_proxy_server_uri_;
606 }
607
608 private:
ryansturm49a8cb12016-06-15 16:51:09609 bool observed_before_headers_sent_with_proxy_;
610 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27611 std::string observed_proxy_server_uri_;
612
ryansturm49a8cb12016-06-15 16:51:09613 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27614};
615
[email protected]15a5ccf82008-10-23 19:57:43616// Fill |str| with a long header list that consumes >= |size| bytes.
617void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51618 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19619 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
620 const int sizeof_row = strlen(row);
621 const int num_rows = static_cast<int>(
622 ceil(static_cast<float>(size) / sizeof_row));
623 const int sizeof_data = num_rows * sizeof_row;
624 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43625 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51626
[email protected]4ddaf2502008-10-23 18:26:19627 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43628 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19629}
630
thakis84dff942015-07-28 20:47:38631#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09632uint64_t MockGetMSTime() {
633 // Tue, 23 May 2017 20:13:07 +0000
634 return 131400439870000000;
635}
636
[email protected]385a4672009-03-11 22:21:29637// Alternative functions that eliminate randomness and dependency on the local
638// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37639void MockGenerateRandom(uint8_t* output, size_t n) {
640 // This is set to 0xaa because the client challenge for testing in
641 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
642 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29643}
644
[email protected]fe2bc6a2009-03-23 16:52:20645std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37646 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29647}
thakis84dff942015-07-28 20:47:38648#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29649
Matt Menked6fd2a52019-03-20 06:14:36650class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31651 public:
Matt Menked6fd2a52019-03-20 06:14:36652 explicit CaptureGroupIdTransportSocketPool(
653 const CommonConnectJobParams* common_connect_job_params)
654 : TransportClientSocketPool(0,
655 0,
656 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36657 ProxyServer::Direct(),
658 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52659 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18660
Matt Menkef6edce752019-03-19 17:21:56661 const ClientSocketPool::GroupId& last_group_id_received() const {
662 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49663 }
664
Tarun Bansal162eabe52018-01-20 01:16:39665 bool socket_requested() const { return socket_requested_; }
666
Matt Menke28ac03e2019-02-25 22:25:50667 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56668 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03669 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28670 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50671 RequestPriority priority,
672 const SocketTag& socket_tag,
673 ClientSocketPool::RespectLimits respect_limits,
674 ClientSocketHandle* handle,
675 CompletionOnceCallback callback,
676 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
677 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56678 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39679 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31680 return ERR_IO_PENDING;
681 }
Matt Menkef6edce752019-03-19 17:21:56682 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21683 ClientSocketHandle* handle,
684 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56685 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09686 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24687 int64_t generation) override {}
Matt Menke433de6d2020-03-04 00:24:11688 void CloseIdleSockets(const char* net_log_reason_utf8) override {}
689 void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
690 const char* net_log_reason_utf8) override {}
dmichaeld6e570d2014-12-18 22:30:57691 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56692 size_t IdleSocketCountInGroup(
693 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31694 return 0;
695 }
Matt Menkef6edce752019-03-19 17:21:56696 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57697 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31698 return LOAD_STATE_IDLE;
699 }
[email protected]d80a4322009-08-14 07:07:49700
701 private:
Matt Menkef6edce752019-03-19 17:21:56702 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39703 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31704};
705
[email protected]231d5a32008-09-13 00:45:27706//-----------------------------------------------------------------------------
707
[email protected]79cb5c12011-09-12 13:12:04708// Helper functions for validating that AuthChallengeInfo's are correctly
709// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58710bool CheckBasicServerAuth(
711 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04712 if (!auth_challenge)
713 return false;
714 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43715 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04716 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19717 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04718 return true;
719}
720
David Benjamin2eb827f2019-04-29 18:31:04721bool CheckBasicSecureServerAuth(
722 const base::Optional<AuthChallengeInfo>& auth_challenge) {
723 if (!auth_challenge)
724 return false;
725 EXPECT_FALSE(auth_challenge->is_proxy);
726 EXPECT_EQ("https://www.example.org", 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 CheckBasicProxyAuth(
733 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04734 if (!auth_challenge)
735 return false;
736 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43737 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
738 EXPECT_EQ("MyRealm1", auth_challenge->realm);
739 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
740 return true;
741}
742
Emily Starkf2c9bbd2019-04-09 17:08:58743bool CheckBasicSecureProxyAuth(
744 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43745 if (!auth_challenge)
746 return false;
747 EXPECT_TRUE(auth_challenge->is_proxy);
748 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04749 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19750 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04751 return true;
752}
753
Emily Starkf2c9bbd2019-04-09 17:08:58754bool CheckDigestServerAuth(
755 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04756 if (!auth_challenge)
757 return false;
758 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43759 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04760 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19761 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04762 return true;
763}
764
thakis84dff942015-07-28 20:47:38765#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58766bool CheckNTLMServerAuth(
767 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04768 if (!auth_challenge)
769 return false;
770 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55771 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04772 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19773 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04774 return true;
775}
David Benjamin5cb91132018-04-06 05:54:49776
Emily Starkf2c9bbd2019-04-09 17:08:58777bool CheckNTLMProxyAuth(
778 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49779 if (!auth_challenge)
780 return false;
781 EXPECT_TRUE(auth_challenge->is_proxy);
782 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
783 EXPECT_EQ(std::string(), auth_challenge->realm);
784 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
785 return true;
786}
thakis84dff942015-07-28 20:47:38787#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04788
[email protected]448d4ca52012-03-04 04:12:23789} // namespace
790
Shivani Sharma8ae506c2019-07-21 21:08:27791// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
792// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
793
bncd16676a2016-07-20 16:23:01794TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09795 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16796 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27797}
798
bncd16676a2016-07-20 16:23:01799TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27800 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35801 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
802 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06803 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27804 };
Ryan Sleevib8d7ea02018-05-07 20:01:01805 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01806 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27807 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
808 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01809 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22810 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47811 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59812
813 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27814}
815
816// Response with no status line.
bncd16676a2016-07-20 16:23:01817TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27818 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35819 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06820 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27821 };
Ryan Sleevib8d7ea02018-05-07 20:01:01822 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41823 EXPECT_THAT(out.rv, IsOk());
824 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
825 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01826 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41827 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27828}
829
mmenkea7da6da2016-09-01 21:56:52830// Response with no status line, and a weird port. Should fail by default.
831TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
832 MockRead data_reads[] = {
833 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
834 };
835
Ryan Sleevib8d7ea02018-05-07 20:01:01836 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52837 session_deps_.socket_factory->AddSocketDataProvider(&data);
838
839 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
840
krasinc06a72a2016-12-21 03:42:46841 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58842 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19843 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52844
mmenkea7da6da2016-09-01 21:56:52845 request.method = "GET";
846 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e2018-02-07 07:41:10847 request.traffic_annotation =
848 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
849
mmenkea7da6da2016-09-01 21:56:52850 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20851 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52852 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
853}
854
Shivani Sharmafdcaefd2017-11-02 00:12:26855// Tests that request info can be destroyed after the headers phase is complete.
856TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
858 auto trans =
859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
860
861 MockRead data_reads[] = {
862 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
863 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
864 };
Ryan Sleevib8d7ea02018-05-07 20:01:01865 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26866 session_deps_.socket_factory->AddSocketDataProvider(&data);
867
868 TestCompletionCallback callback;
869
870 {
871 auto request = std::make_unique<HttpRequestInfo>();
872 request->method = "GET";
873 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10874 request->traffic_annotation =
875 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26876
877 int rv =
878 trans->Start(request.get(), callback.callback(), NetLogWithSource());
879
880 EXPECT_THAT(callback.GetResult(rv), IsOk());
881 } // Let request info be destroyed.
882
883 trans.reset();
884}
885
dalyk6d7a8c52019-12-18 21:43:01886// Test that a failure in resolving the hostname is retrievable.
887TEST_F(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
888 HttpRequestInfo request;
889 request.method = "GET";
890 request.url = GURL("http://www.example.org/");
891 request.traffic_annotation =
892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
893
894 RecordingTestNetLog log;
895 MockHostResolver* resolver = new MockHostResolver();
896 resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
897 session_deps_.net_log = &log;
898 session_deps_.host_resolver.reset(resolver);
899 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
900 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
901 TestCompletionCallback callback;
902
903 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
904 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
905 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
906
907 const HttpResponseInfo* response = trans.GetResponseInfo();
908 ASSERT_TRUE(response);
909 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
910}
911
[email protected]231d5a32008-09-13 00:45:27912// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01913TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27914 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35915 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06916 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27917 };
Ryan Sleevib8d7ea02018-05-07 20:01:01918 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01919 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27920 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
921 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01922 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22923 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27924}
925
926// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01927TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27928 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35929 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06930 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27931 };
Ryan Sleevib8d7ea02018-05-07 20:01:01932 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01933 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27934 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
935 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01936 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22937 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27938}
939
940// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01941TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27942 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35943 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06944 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27945 };
Ryan Sleevib8d7ea02018-05-07 20:01:01946 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41947 EXPECT_THAT(out.rv, IsOk());
948 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
949 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01950 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41951 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27952}
953
954// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01955TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27956 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35957 MockRead("\n"),
958 MockRead("\n"),
959 MockRead("Q"),
960 MockRead("J"),
961 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06962 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27963 };
Ryan Sleevib8d7ea02018-05-07 20:01:01964 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01965 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27966 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
967 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01968 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22969 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27970}
971
972// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01973TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27974 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35975 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06976 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27977 };
Ryan Sleevib8d7ea02018-05-07 20:01:01978 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41979 EXPECT_THAT(out.rv, IsOk());
980 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
981 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01982 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41983 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52984}
985
[email protected]f9d44aa2008-09-23 23:57:17986// Simulate a 204 response, lacking a Content-Length header, sent over a
987// persistent connection. The response should still terminate since a 204
988// cannot have a response body.
bncd16676a2016-07-20 16:23:01989TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19990 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17991 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35992 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19993 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06994 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17995 };
Ryan Sleevib8d7ea02018-05-07 20:01:01996 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01997 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17998 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
999 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011000 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221001 int64_t response_size = reads_size - strlen(junk);
1002 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171003}
1004
[email protected]0877e3d2009-10-17 22:29:571005// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011006TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191007 std::string final_chunk = "0\r\n\r\n";
1008 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1009 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571010 MockRead data_reads[] = {
1011 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1012 MockRead("5\r\nHello\r\n"),
1013 MockRead("1\r\n"),
1014 MockRead(" \r\n"),
1015 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191016 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061017 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571018 };
Ryan Sleevib8d7ea02018-05-07 20:01:011019 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011020 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571021 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1022 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011023 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221024 int64_t response_size = reads_size - extra_data.size();
1025 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571026}
1027
[email protected]9fe44f52010-09-23 18:36:001028// Next tests deal with http://crbug.com/56344.
1029
bncd16676a2016-07-20 16:23:011030TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001031 MultipleContentLengthHeadersNoTransferEncoding) {
1032 MockRead data_reads[] = {
1033 MockRead("HTTP/1.1 200 OK\r\n"),
1034 MockRead("Content-Length: 10\r\n"),
1035 MockRead("Content-Length: 5\r\n\r\n"),
1036 };
Ryan Sleevib8d7ea02018-05-07 20:01:011037 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011038 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001039}
1040
bncd16676a2016-07-20 16:23:011041TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041042 DuplicateContentLengthHeadersNoTransferEncoding) {
1043 MockRead data_reads[] = {
1044 MockRead("HTTP/1.1 200 OK\r\n"),
1045 MockRead("Content-Length: 5\r\n"),
1046 MockRead("Content-Length: 5\r\n\r\n"),
1047 MockRead("Hello"),
1048 };
Ryan Sleevib8d7ea02018-05-07 20:01:011049 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011050 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041051 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1052 EXPECT_EQ("Hello", out.response_data);
1053}
1054
bncd16676a2016-07-20 16:23:011055TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041056 ComplexContentLengthHeadersNoTransferEncoding) {
1057 // More than 2 dupes.
1058 {
1059 MockRead data_reads[] = {
1060 MockRead("HTTP/1.1 200 OK\r\n"),
1061 MockRead("Content-Length: 5\r\n"),
1062 MockRead("Content-Length: 5\r\n"),
1063 MockRead("Content-Length: 5\r\n\r\n"),
1064 MockRead("Hello"),
1065 };
Ryan Sleevib8d7ea02018-05-07 20:01:011066 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011067 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041068 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1069 EXPECT_EQ("Hello", out.response_data);
1070 }
1071 // HTTP/1.0
1072 {
1073 MockRead data_reads[] = {
1074 MockRead("HTTP/1.0 200 OK\r\n"),
1075 MockRead("Content-Length: 5\r\n"),
1076 MockRead("Content-Length: 5\r\n"),
1077 MockRead("Content-Length: 5\r\n\r\n"),
1078 MockRead("Hello"),
1079 };
Ryan Sleevib8d7ea02018-05-07 20:01:011080 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011081 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041082 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1083 EXPECT_EQ("Hello", out.response_data);
1084 }
1085 // 2 dupes and one mismatched.
1086 {
1087 MockRead data_reads[] = {
1088 MockRead("HTTP/1.1 200 OK\r\n"),
1089 MockRead("Content-Length: 10\r\n"),
1090 MockRead("Content-Length: 10\r\n"),
1091 MockRead("Content-Length: 5\r\n\r\n"),
1092 };
Ryan Sleevib8d7ea02018-05-07 20:01:011093 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011094 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041095 }
1096}
1097
bncd16676a2016-07-20 16:23:011098TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001099 MultipleContentLengthHeadersTransferEncoding) {
1100 MockRead data_reads[] = {
1101 MockRead("HTTP/1.1 200 OK\r\n"),
1102 MockRead("Content-Length: 666\r\n"),
1103 MockRead("Content-Length: 1337\r\n"),
1104 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1105 MockRead("5\r\nHello\r\n"),
1106 MockRead("1\r\n"),
1107 MockRead(" \r\n"),
1108 MockRead("5\r\nworld\r\n"),
1109 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061110 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001111 };
Ryan Sleevib8d7ea02018-05-07 20:01:011112 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011113 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001114 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1115 EXPECT_EQ("Hello world", out.response_data);
1116}
1117
[email protected]1628fe92011-10-04 23:04:551118// Next tests deal with http://crbug.com/98895.
1119
1120// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011121TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551122 MockRead data_reads[] = {
1123 MockRead("HTTP/1.1 200 OK\r\n"),
1124 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1125 MockRead("Content-Length: 5\r\n\r\n"),
1126 MockRead("Hello"),
1127 };
Ryan Sleevib8d7ea02018-05-07 20:01:011128 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011129 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551130 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1131 EXPECT_EQ("Hello", out.response_data);
1132}
1133
[email protected]54a9c6e52012-03-21 20:10:591134// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011135TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551136 MockRead data_reads[] = {
1137 MockRead("HTTP/1.1 200 OK\r\n"),
1138 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1139 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1140 MockRead("Content-Length: 5\r\n\r\n"),
1141 MockRead("Hello"),
1142 };
Ryan Sleevib8d7ea02018-05-07 20:01:011143 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011144 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591145 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1146 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551147}
1148
1149// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011150TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551151 MockRead data_reads[] = {
1152 MockRead("HTTP/1.1 200 OK\r\n"),
1153 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1154 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1155 MockRead("Content-Length: 5\r\n\r\n"),
1156 MockRead("Hello"),
1157 };
Ryan Sleevib8d7ea02018-05-07 20:01:011158 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011159 EXPECT_THAT(out.rv,
1160 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551161}
1162
[email protected]54a9c6e52012-03-21 20:10:591163// Checks that two identical Location headers result in no error.
1164// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011165TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551166 MockRead data_reads[] = {
1167 MockRead("HTTP/1.1 302 Redirect\r\n"),
1168 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591169 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551170 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061171 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551172 };
1173
1174 HttpRequestInfo request;
1175 request.method = "GET";
1176 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101177 request.traffic_annotation =
1178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551179
danakj1fd259a02016-04-16 03:17:091180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551182
Ryan Sleevib8d7ea02018-05-07 20:01:011183 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071184 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551185
[email protected]49639fa2011-12-20 23:22:411186 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551187
tfarina42834112016-09-22 13:38:201188 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011189 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551190
robpercival214763f2016-07-01 23:27:011191 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551192
bnc691fda62016-08-12 00:43:161193 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521194 ASSERT_TRUE(response);
1195 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551196 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1197 std::string url;
1198 EXPECT_TRUE(response->headers->IsRedirect(&url));
1199 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471200 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551201}
1202
[email protected]1628fe92011-10-04 23:04:551203// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011204TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551205 MockRead data_reads[] = {
1206 MockRead("HTTP/1.1 302 Redirect\r\n"),
1207 MockRead("Location: http://good.com/\r\n"),
1208 MockRead("Location: http://evil.com/\r\n"),
1209 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061210 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551211 };
Ryan Sleevib8d7ea02018-05-07 20:01:011212 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551214}
1215
[email protected]ef0faf2e72009-03-05 23:27:231216// Do a request using the HEAD method. Verify that we don't try to read the
1217// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011218TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421219 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231220 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231221 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101222 request.traffic_annotation =
1223 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231224
danakj1fd259a02016-04-16 03:17:091225 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161226 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091227 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161228 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091229 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1230 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271231
[email protected]ef0faf2e72009-03-05 23:27:231232 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131233 MockWrite("HEAD / HTTP/1.1\r\n"
1234 "Host: www.example.org\r\n"
1235 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231236 };
1237 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231238 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1239 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231240
mmenked39192ee2015-12-09 00:57:231241 // No response body because the test stops reading here.
1242 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231243 };
1244
Ryan Sleevib8d7ea02018-05-07 20:01:011245 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071246 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231247
[email protected]49639fa2011-12-20 23:22:411248 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231249
tfarina42834112016-09-22 13:38:201250 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231252
1253 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011254 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231255
bnc691fda62016-08-12 00:43:161256 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521257 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231258
1259 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521260 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231261 EXPECT_EQ(1234, response->headers->GetContentLength());
1262 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471263 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091264 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1265 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231266
1267 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101268 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231269 bool has_server_header = response->headers->EnumerateHeader(
1270 &iter, "Server", &server_header);
1271 EXPECT_TRUE(has_server_header);
1272 EXPECT_EQ("Blah", server_header);
1273
1274 // Reading should give EOF right away, since there is no message body
1275 // (despite non-zero content-length).
1276 std::string response_data;
bnc691fda62016-08-12 00:43:161277 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011278 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231279 EXPECT_EQ("", response_data);
1280}
1281
bncd16676a2016-07-20 16:23:011282TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091283 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521284
1285 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351286 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1287 MockRead("hello"),
1288 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1289 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061290 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521291 };
Ryan Sleevib8d7ea02018-05-07 20:01:011292 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071293 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521294
[email protected]0b0bf032010-09-21 18:08:501295 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521296 "hello", "world"
1297 };
1298
1299 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421300 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521301 request.method = "GET";
bncce36dca22015-04-21 22:11:231302 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101303 request.traffic_annotation =
1304 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521305
bnc691fda62016-08-12 00:43:161306 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271307
[email protected]49639fa2011-12-20 23:22:411308 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521309
tfarina42834112016-09-22 13:38:201310 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011311 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521312
1313 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011314 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521315
bnc691fda62016-08-12 00:43:161316 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521317 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521318
wezca1070932016-05-26 20:30:521319 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251320 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471321 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521322
1323 std::string response_data;
bnc691fda62016-08-12 00:43:161324 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011325 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251326 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521327 }
1328}
1329
bncd16676a2016-07-20 16:23:011330TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091331 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221332 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191333 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221334 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271335
[email protected]1c773ea12009-04-28 19:58:421336 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521337 request.method = "POST";
1338 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271339 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:101340 request.traffic_annotation =
1341 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521342
shivanishab9a143952016-09-19 17:23:411343 // Check the upload progress returned before initialization is correct.
1344 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1345 EXPECT_EQ(0u, progress.size());
1346 EXPECT_EQ(0u, progress.position());
1347
danakj1fd259a02016-04-16 03:17:091348 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161349 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271350
initial.commit586acc5fe2008-07-26 22:42:521351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351352 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1353 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1354 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061355 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521356 };
Ryan Sleevib8d7ea02018-05-07 20:01:011357 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071358 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521359
[email protected]49639fa2011-12-20 23:22:411360 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521361
tfarina42834112016-09-22 13:38:201362 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011363 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521364
1365 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011366 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521367
bnc691fda62016-08-12 00:43:161368 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521369 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521370
wezca1070932016-05-26 20:30:521371 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251372 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521373
1374 std::string response_data;
bnc691fda62016-08-12 00:43:161375 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011376 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251377 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521378}
1379
[email protected]3a2d3662009-03-27 03:49:141380// This test is almost the same as Ignores100 above, but the response contains
1381// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571382// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011383TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421384 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141385 request.method = "GET";
1386 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101387 request.traffic_annotation =
1388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141389
danakj1fd259a02016-04-16 03:17:091390 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161391 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271392
[email protected]3a2d3662009-03-27 03:49:141393 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571394 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1395 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141396 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061397 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141398 };
Ryan Sleevib8d7ea02018-05-07 20:01:011399 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071400 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141401
[email protected]49639fa2011-12-20 23:22:411402 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141403
tfarina42834112016-09-22 13:38:201404 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011405 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141406
1407 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011408 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141409
bnc691fda62016-08-12 00:43:161410 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521411 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141412
wezca1070932016-05-26 20:30:521413 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141414 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1415
1416 std::string response_data;
bnc691fda62016-08-12 00:43:161417 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011418 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141419 EXPECT_EQ("hello world", response_data);
1420}
1421
Andrew Comminos517a92c2019-01-14 17:49:561422TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1423 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381424 base::TimeDelta::FromMilliseconds(10);
1425
1426 HttpRequestInfo request;
1427 request.method = "GET";
1428 request.url = GURL("http://www.foo.com/");
1429 request.traffic_annotation =
1430 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1431
1432 std::vector<MockWrite> data_writes = {
1433 MockWrite(ASYNC, 0,
1434 "GET / HTTP/1.1\r\n"
1435 "Host: www.foo.com\r\n"
1436 "Connection: keep-alive\r\n\r\n"),
1437 };
1438
1439 std::vector<MockRead> data_reads = {
1440 // Write one byte of the status line, followed by a pause.
1441 MockRead(ASYNC, 1, "H"),
1442 MockRead(ASYNC, ERR_IO_PENDING, 2),
1443 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1444 MockRead(ASYNC, 4, "hello world"),
1445 MockRead(SYNCHRONOUS, OK, 5),
1446 };
1447
1448 SequencedSocketData data(data_reads, data_writes);
1449 session_deps_.socket_factory->AddSocketDataProvider(&data);
1450
1451 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1452
1453 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1454
1455 TestCompletionCallback callback;
1456
1457 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1458 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1459
1460 data.RunUntilPaused();
1461 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561462 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381463 data.Resume();
1464
1465 rv = callback.WaitForResult();
1466 EXPECT_THAT(rv, IsOk());
1467
1468 const HttpResponseInfo* response = trans.GetResponseInfo();
1469 ASSERT_TRUE(response);
1470
1471 EXPECT_TRUE(response->headers);
1472 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1473
1474 LoadTimingInfo load_timing_info;
1475 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1476 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1477 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561478 // Ensure we didn't include the delay in the TTFB time.
1479 EXPECT_EQ(load_timing_info.receive_headers_start,
1480 load_timing_info.connect_timing.connect_end);
1481 // Ensure that the mock clock advanced at all.
1482 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1483 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381484
1485 std::string response_data;
1486 rv = ReadTransaction(&trans, &response_data);
1487 EXPECT_THAT(rv, IsOk());
1488 EXPECT_EQ("hello world", response_data);
1489}
1490
1491// Tests that the time-to-first-byte reported in a transaction's load timing
1492// info uses the first response, even if 1XX/informational.
1493void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561494 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381495 base::TimeDelta::FromMilliseconds(10);
1496
1497 HttpRequestInfo request;
1498 request.method = "GET";
1499 request.url = GURL("https://www.foo.com/");
1500 request.traffic_annotation =
1501 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1502
1503 SSLSocketDataProvider ssl(ASYNC, OK);
1504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1505
1506 std::vector<MockWrite> data_writes;
1507 std::vector<MockRead> data_reads;
1508
1509 spdy::SpdySerializedFrame spdy_req(
1510 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1511
1512 spdy::SpdyHeaderBlock spdy_resp1_headers;
1513 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1514 spdy::SpdySerializedFrame spdy_resp1(
1515 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1516 spdy::SpdySerializedFrame spdy_resp2(
1517 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1518 spdy::SpdySerializedFrame spdy_data(
1519 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1520
1521 if (use_spdy) {
1522 ssl.next_proto = kProtoHTTP2;
1523
1524 data_writes = {CreateMockWrite(spdy_req, 0)};
1525
1526 data_reads = {
1527 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1528 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1529 MockRead(SYNCHRONOUS, OK, 5),
1530 };
1531 } else {
1532 data_writes = {
1533 MockWrite(ASYNC, 0,
1534 "GET / HTTP/1.1\r\n"
1535 "Host: www.foo.com\r\n"
1536 "Connection: keep-alive\r\n\r\n"),
1537 };
1538
1539 data_reads = {
1540 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1541 MockRead(ASYNC, ERR_IO_PENDING, 2),
1542
1543 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1544 MockRead(ASYNC, 4, "hello world"),
1545 MockRead(SYNCHRONOUS, OK, 5),
1546 };
1547 }
1548
1549 SequencedSocketData data(data_reads, data_writes);
1550 session_deps_.socket_factory->AddSocketDataProvider(&data);
1551
1552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1553
1554 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1555
1556 TestCompletionCallback callback;
1557
1558 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1559 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1560
1561 data.RunUntilPaused();
1562 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1563 // the delay before parsing the 200 response.
1564 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561565 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381566 data.Resume();
1567
1568 rv = callback.WaitForResult();
1569 EXPECT_THAT(rv, IsOk());
1570
1571 const HttpResponseInfo* response = trans.GetResponseInfo();
1572 ASSERT_TRUE(response);
1573
1574 LoadTimingInfo load_timing_info;
1575 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1576 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1577 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561578 // Ensure we didn't include the delay in the TTFB time.
1579 EXPECT_EQ(load_timing_info.receive_headers_start,
1580 load_timing_info.connect_timing.connect_end);
1581 // Ensure that the mock clock advanced at all.
1582 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1583 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381584
1585 std::string response_data;
1586 rv = ReadTransaction(&trans, &response_data);
1587 EXPECT_THAT(rv, IsOk());
1588 EXPECT_EQ("hello world", response_data);
1589}
1590
Andrew Comminos517a92c2019-01-14 17:49:561591TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381592 Check100ResponseTiming(false /* use_spdy */);
1593}
1594
Andrew Comminos517a92c2019-01-14 17:49:561595TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381596 Check100ResponseTiming(true /* use_spdy */);
1597}
1598
bncd16676a2016-07-20 16:23:011599TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081600 HttpRequestInfo request;
1601 request.method = "POST";
1602 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101603 request.traffic_annotation =
1604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081605
danakj1fd259a02016-04-16 03:17:091606 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161607 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081608
1609 MockRead data_reads[] = {
1610 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1611 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381612 };
Ryan Sleevib8d7ea02018-05-07 20:01:011613 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081614 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381615
zmo9528c9f42015-08-04 22:12:081616 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381617
tfarina42834112016-09-22 13:38:201618 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011619 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381620
zmo9528c9f42015-08-04 22:12:081621 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011622 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381623
zmo9528c9f42015-08-04 22:12:081624 std::string response_data;
bnc691fda62016-08-12 00:43:161625 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011626 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081627 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381628}
1629
bncd16676a2016-07-20 16:23:011630TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381631 HttpRequestInfo request;
1632 request.method = "POST";
1633 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101634 request.traffic_annotation =
1635 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381636
danakj1fd259a02016-04-16 03:17:091637 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271639
[email protected]ee9410e72010-01-07 01:42:381640 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061641 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381642 };
Ryan Sleevib8d7ea02018-05-07 20:01:011643 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071644 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381645
[email protected]49639fa2011-12-20 23:22:411646 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381647
tfarina42834112016-09-22 13:38:201648 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011649 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381650
1651 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011652 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381653}
1654
[email protected]23e482282013-06-14 16:08:021655void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511656 const MockWrite* write_failure,
1657 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421658 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521659 request.method = "GET";
1660 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101661 request.traffic_annotation =
1662 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521663
Matt Muellerd9342e3a2019-11-26 01:41:141664 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071665 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091666 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271667
[email protected]202965992011-12-07 23:04:511668 // Written data for successfully sending both requests.
1669 MockWrite data1_writes[] = {
1670 MockWrite("GET / HTTP/1.1\r\n"
1671 "Host: www.foo.com\r\n"
1672 "Connection: keep-alive\r\n\r\n"),
1673 MockWrite("GET / HTTP/1.1\r\n"
1674 "Host: www.foo.com\r\n"
1675 "Connection: keep-alive\r\n\r\n")
1676 };
1677
1678 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521679 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351680 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1681 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061682 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521683 };
[email protected]202965992011-12-07 23:04:511684
1685 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491686 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511687 data1_writes[1] = *write_failure;
1688 } else {
1689 ASSERT_TRUE(read_failure);
1690 data1_reads[2] = *read_failure;
1691 }
1692
Ryan Sleevib8d7ea02018-05-07 20:01:011693 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071694 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521695
1696 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351697 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1698 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061699 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521700 };
Ryan Sleevib8d7ea02018-05-07 20:01:011701 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071702 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521703
thestig9d3bb0c2015-01-24 00:49:511704 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521705 "hello", "world"
1706 };
1707
mikecironef22f9812016-10-04 03:40:191708 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521709 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411710 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521711
bnc691fda62016-08-12 00:43:161712 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521713
tfarina42834112016-09-22 13:38:201714 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011715 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521716
1717 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011718 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521719
[email protected]58e32bb2013-01-21 18:23:251720 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161721 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251722 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1723 if (i == 0) {
1724 first_socket_log_id = load_timing_info.socket_log_id;
1725 } else {
1726 // The second request should be using a new socket.
1727 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1728 }
1729
bnc691fda62016-08-12 00:43:161730 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521731 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521732
wezca1070932016-05-26 20:30:521733 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471734 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251735 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521736
1737 std::string response_data;
bnc691fda62016-08-12 00:43:161738 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011739 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251740 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521741 }
1742}
[email protected]3d2a59b2008-09-26 19:44:251743
[email protected]a34f61ee2014-03-18 20:59:491744void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1745 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101746 const MockRead* read_failure,
1747 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491748 HttpRequestInfo request;
1749 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101750 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101751 request.traffic_annotation =
1752 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491753
Matt Muellerd9342e3a2019-11-26 01:41:141754 RecordingTestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491755 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491757
[email protected]09356c652014-03-25 15:36:101758 SSLSocketDataProvider ssl1(ASYNC, OK);
1759 SSLSocketDataProvider ssl2(ASYNC, OK);
1760 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361761 ssl1.next_proto = kProtoHTTP2;
1762 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101763 }
1764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1765 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491766
[email protected]09356c652014-03-25 15:36:101767 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131768 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491769 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131770 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351771 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131772 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191773 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491774
[email protected]09356c652014-03-25 15:36:101775 // HTTP/1.1 versions of the request and response.
1776 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1777 "Host: www.foo.com\r\n"
1778 "Connection: keep-alive\r\n\r\n";
1779 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1780 const char kHttpData[] = "hello";
1781
1782 std::vector<MockRead> data1_reads;
1783 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491784 if (write_failure) {
1785 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101786 data1_writes.push_back(*write_failure);
1787 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491788 } else {
1789 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101790 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411791 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101792 } else {
1793 data1_writes.push_back(MockWrite(kHttpRequest));
1794 }
1795 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491796 }
1797
Ryan Sleevib8d7ea02018-05-07 20:01:011798 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491799 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1800
[email protected]09356c652014-03-25 15:36:101801 std::vector<MockRead> data2_reads;
1802 std::vector<MockWrite> data2_writes;
1803
1804 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411805 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101806
bncdf80d44fd2016-07-15 20:27:411807 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1808 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101809 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1810 } else {
1811 data2_writes.push_back(
1812 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1813
1814 data2_reads.push_back(
1815 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1816 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1817 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1818 }
Ryan Sleevib8d7ea02018-05-07 20:01:011819 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491820 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1821
1822 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591823 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491824 // Wait for the preconnect to complete.
1825 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1826 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231827 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491828
1829 // Make the request.
1830 TestCompletionCallback callback;
1831
bnc691fda62016-08-12 00:43:161832 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491833
tfarina42834112016-09-22 13:38:201834 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491836
1837 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011838 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491839
1840 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161841 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101842 TestLoadTimingNotReused(
1843 load_timing_info,
1844 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491845
bnc691fda62016-08-12 00:43:161846 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521847 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491848
wezca1070932016-05-26 20:30:521849 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021850 if (response->was_fetched_via_spdy) {
1851 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1852 } else {
1853 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1854 }
[email protected]a34f61ee2014-03-18 20:59:491855
1856 std::string response_data;
bnc691fda62016-08-12 00:43:161857 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011858 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101859 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491860}
1861
Biljith Jayan45a41722017-08-16 18:43:141862// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181863// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141864// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1865TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1866 HttpRequestInfo request;
1867 request.method = "GET";
1868 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101869 request.traffic_annotation =
1870 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141871
1872 // Check whether we give up after the third try.
1873
1874 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131875 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141876 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131877 spdy::SpdySerializedFrame spdy_response_go_away(
1878 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011879 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1880 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141881
1882 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011883 StaticSocketDataProvider data1(data_read1, data_write);
1884 StaticSocketDataProvider data2(data_read1, data_write);
1885 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141886
1887 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1888 AddSSLSocketData();
1889 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1890 AddSSLSocketData();
1891 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1892 AddSSLSocketData();
1893
1894 TestCompletionCallback callback;
1895 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1896 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1897
1898 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1899 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1900
1901 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181902 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141903}
1904
1905TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1906 HttpRequestInfo request;
1907 request.method = "GET";
1908 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101909 request.traffic_annotation =
1910 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141911
1912 // Check whether we try atleast thrice before giving up.
1913
1914 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131915 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141916 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131917 spdy::SpdySerializedFrame spdy_response_go_away(
1918 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011919 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1920 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141921
1922 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131923 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141924 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131925 spdy::SpdySerializedFrame spdy_data(
1926 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141927 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1928 CreateMockRead(spdy_data, 2)};
1929
1930 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011931 StaticSocketDataProvider data1(data_read1, data_write);
1932 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141933 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011934 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141935
1936 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1937 AddSSLSocketData();
1938 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1939 AddSSLSocketData();
1940 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1941 AddSSLSocketData();
1942
1943 TestCompletionCallback callback;
1944 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1946
1947 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1949
1950 rv = callback.WaitForResult();
1951 EXPECT_THAT(rv, IsOk());
1952}
1953
bncd16676a2016-07-20 16:23:011954TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061955 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351956 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511957}
1958
bncd16676a2016-07-20 16:23:011959TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061960 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351961 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251962}
1963
bncd16676a2016-07-20 16:23:011964TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061965 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351966 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251967}
1968
[email protected]d58ceea82014-06-04 10:55:541969// Make sure that on a 408 response (Request Timeout), the request is retried,
1970// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011971TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541972 MockRead read_failure(SYNCHRONOUS,
1973 "HTTP/1.1 408 Request Timeout\r\n"
1974 "Connection: Keep-Alive\r\n"
1975 "Content-Length: 6\r\n\r\n"
1976 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351977 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541978}
1979
bncd16676a2016-07-20 16:23:011980TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491981 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351982 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491983}
1984
bncd16676a2016-07-20 16:23:011985TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491986 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351987 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491988}
1989
bncd16676a2016-07-20 16:23:011990TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491991 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351992 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101993}
1994
bncd16676a2016-07-20 16:23:011995TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101996 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351997 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101998}
1999
[email protected]d58ceea82014-06-04 10:55:542000// Make sure that on a 408 response (Request Timeout), the request is retried,
2001// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012002TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542003 MockRead read_failure(SYNCHRONOUS,
2004 "HTTP/1.1 408 Request Timeout\r\n"
2005 "Connection: Keep-Alive\r\n"
2006 "Content-Length: 6\r\n\r\n"
2007 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352008 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2009 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:542010}
2011
bncd16676a2016-07-20 16:23:012012TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102013 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352014 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:102015}
2016
bncd16676a2016-07-20 16:23:012017TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102018 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352019 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102020}
2021
bncd16676a2016-07-20 16:23:012022TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102023 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352024 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102025}
2026
bncd16676a2016-07-20 16:23:012027TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102028 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352029 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:492030}
2031
bncd16676a2016-07-20 16:23:012032TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422033 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252034 request.method = "GET";
bncce36dca22015-04-21 22:11:232035 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102036 request.traffic_annotation =
2037 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252038
danakj1fd259a02016-04-16 03:17:092039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272041
[email protected]3d2a59b2008-09-26 19:44:252042 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062043 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352044 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2045 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062046 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252047 };
Ryan Sleevib8d7ea02018-05-07 20:01:012048 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072049 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252050
[email protected]49639fa2011-12-20 23:22:412051 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252052
tfarina42834112016-09-22 13:38:202053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252055
2056 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012057 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592058
2059 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162060 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592061 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252062}
2063
2064// What do various browsers do when the server closes a non-keepalive
2065// connection without sending any response header or body?
2066//
2067// IE7: error page
2068// Safari 3.1.2 (Windows): error page
2069// Firefox 3.0.1: blank page
2070// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422071// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2072// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012073TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252074 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062075 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352076 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2077 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062078 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252079 };
Ryan Sleevib8d7ea02018-05-07 20:01:012080 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012081 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252082}
[email protected]1826a402014-01-08 15:40:482083
[email protected]7a5378b2012-11-04 03:25:172084// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2085// tests. There was a bug causing HttpNetworkTransaction to hang in the
2086// destructor in such situations.
2087// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012088TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172089 HttpRequestInfo request;
2090 request.method = "GET";
bncce36dca22015-04-21 22:11:232091 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102092 request.traffic_annotation =
2093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172094
danakj1fd259a02016-04-16 03:17:092095 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582096 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192097 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172098
2099 MockRead data_reads[] = {
2100 MockRead("HTTP/1.0 200 OK\r\n"),
2101 MockRead("Connection: keep-alive\r\n"),
2102 MockRead("Content-Length: 100\r\n\r\n"),
2103 MockRead("hello"),
2104 MockRead(SYNCHRONOUS, 0),
2105 };
Ryan Sleevib8d7ea02018-05-07 20:01:012106 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072107 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172108
2109 TestCompletionCallback callback;
2110
tfarina42834112016-09-22 13:38:202111 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012112 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172113
2114 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012115 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172116
Victor Costan9c7302b2018-08-27 16:39:442117 scoped_refptr<IOBufferWithSize> io_buf =
2118 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502119 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172120 if (rv == ERR_IO_PENDING)
2121 rv = callback.WaitForResult();
2122 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502123 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012124 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172125
2126 trans.reset();
fdoray92e35a72016-06-10 15:54:552127 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172128 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2129}
2130
bncd16676a2016-07-20 16:23:012131TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172132 HttpRequestInfo request;
2133 request.method = "GET";
bncce36dca22015-04-21 22:11:232134 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102135 request.traffic_annotation =
2136 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172137
danakj1fd259a02016-04-16 03:17:092138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582139 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192140 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172141
2142 MockRead data_reads[] = {
2143 MockRead("HTTP/1.0 200 OK\r\n"),
2144 MockRead("Connection: keep-alive\r\n"),
2145 MockRead("Content-Length: 100\r\n\r\n"),
2146 MockRead(SYNCHRONOUS, 0),
2147 };
Ryan Sleevib8d7ea02018-05-07 20:01:012148 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072149 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172150
2151 TestCompletionCallback callback;
2152
tfarina42834112016-09-22 13:38:202153 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012154 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172155
2156 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012157 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172158
Victor Costan9c7302b2018-08-27 16:39:442159 scoped_refptr<IOBufferWithSize> io_buf(
2160 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502161 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172162 if (rv == ERR_IO_PENDING)
2163 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012164 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172165
2166 trans.reset();
fdoray92e35a72016-06-10 15:54:552167 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172168 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2169}
2170
[email protected]0b0bf032010-09-21 18:08:502171// Test that we correctly reuse a keep-alive connection after not explicitly
2172// reading the body.
bncd16676a2016-07-20 16:23:012173TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132174 HttpRequestInfo request;
2175 request.method = "GET";
2176 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102177 request.traffic_annotation =
2178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132179
Matt Muellerd9342e3a2019-11-26 01:41:142180 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072181 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092182 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272183
mmenkecc2298e2015-12-07 18:20:182184 const char* request_data =
2185 "GET / HTTP/1.1\r\n"
2186 "Host: www.foo.com\r\n"
2187 "Connection: keep-alive\r\n\r\n";
2188 MockWrite data_writes[] = {
2189 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2190 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2191 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2192 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2193 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2194 };
2195
[email protected]0b0bf032010-09-21 18:08:502196 // Note that because all these reads happen in the same
2197 // StaticSocketDataProvider, it shows that the same socket is being reused for
2198 // all transactions.
mmenkecc2298e2015-12-07 18:20:182199 MockRead data_reads[] = {
2200 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2201 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2202 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2203 MockRead(ASYNC, 7,
2204 "HTTP/1.1 302 Found\r\n"
2205 "Content-Length: 0\r\n\r\n"),
2206 MockRead(ASYNC, 9,
2207 "HTTP/1.1 302 Found\r\n"
2208 "Content-Length: 5\r\n\r\n"
2209 "hello"),
2210 MockRead(ASYNC, 11,
2211 "HTTP/1.1 301 Moved Permanently\r\n"
2212 "Content-Length: 0\r\n\r\n"),
2213 MockRead(ASYNC, 13,
2214 "HTTP/1.1 301 Moved Permanently\r\n"
2215 "Content-Length: 5\r\n\r\n"
2216 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132217
mmenkecc2298e2015-12-07 18:20:182218 // In the next two rounds, IsConnectedAndIdle returns false, due to
2219 // the set_busy_before_sync_reads(true) call, while the
2220 // HttpNetworkTransaction is being shut down, but the socket is still
2221 // reuseable. See http://crbug.com/544255.
2222 MockRead(ASYNC, 15,
2223 "HTTP/1.1 200 Hunky-Dory\r\n"
2224 "Content-Length: 5\r\n\r\n"),
2225 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132226
mmenkecc2298e2015-12-07 18:20:182227 MockRead(ASYNC, 18,
2228 "HTTP/1.1 200 Hunky-Dory\r\n"
2229 "Content-Length: 5\r\n\r\n"
2230 "he"),
2231 MockRead(SYNCHRONOUS, 19, "llo"),
2232
2233 // The body of the final request is actually read.
2234 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2235 MockRead(ASYNC, 22, "hello"),
2236 };
Ryan Sleevib8d7ea02018-05-07 20:01:012237 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182238 data.set_busy_before_sync_reads(true);
2239 session_deps_.socket_factory->AddSocketDataProvider(&data);
2240
Avi Drissman4365a4782018-12-28 19:26:242241 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502242 std::string response_lines[kNumUnreadBodies];
2243
mikecironef22f9812016-10-04 03:40:192244 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182245 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412246 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132247
Jeremy Roman0579ed62017-08-29 15:56:192248 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582249 session.get());
[email protected]fc31d6a42010-06-24 18:05:132250
tfarina42834112016-09-22 13:38:202251 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012252 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132253
[email protected]58e32bb2013-01-21 18:23:252254 LoadTimingInfo load_timing_info;
2255 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2256 if (i == 0) {
2257 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2258 first_socket_log_id = load_timing_info.socket_log_id;
2259 } else {
2260 TestLoadTimingReused(load_timing_info);
2261 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2262 }
2263
[email protected]fc31d6a42010-06-24 18:05:132264 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182265 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132266
mmenkecc2298e2015-12-07 18:20:182267 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502268 response_lines[i] = response->headers->GetStatusLine();
2269
mmenkecc2298e2015-12-07 18:20:182270 // Delete the transaction without reading the response bodies. Then spin
2271 // the message loop, so the response bodies are drained.
2272 trans.reset();
2273 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132274 }
[email protected]0b0bf032010-09-21 18:08:502275
2276 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182277 "HTTP/1.1 204 No Content",
2278 "HTTP/1.1 205 Reset Content",
2279 "HTTP/1.1 304 Not Modified",
2280 "HTTP/1.1 302 Found",
2281 "HTTP/1.1 302 Found",
2282 "HTTP/1.1 301 Moved Permanently",
2283 "HTTP/1.1 301 Moved Permanently",
2284 "HTTP/1.1 200 Hunky-Dory",
2285 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502286 };
2287
Avi Drissman4365a4782018-12-28 19:26:242288 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272289 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502290
2291 for (int i = 0; i < kNumUnreadBodies; ++i)
2292 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2293
[email protected]49639fa2011-12-20 23:22:412294 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162295 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202296 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012297 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162298 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182299 ASSERT_TRUE(response);
2300 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502301 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2302 std::string response_data;
bnc691fda62016-08-12 00:43:162303 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012304 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502305 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132306}
2307
mmenke5f94fda2016-06-02 20:54:132308// Sockets that receive extra data after a response is complete should not be
2309// reused.
bncd16676a2016-07-20 16:23:012310TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132311 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2312 MockWrite data_writes1[] = {
2313 MockWrite("HEAD / HTTP/1.1\r\n"
2314 "Host: www.borked.com\r\n"
2315 "Connection: keep-alive\r\n\r\n"),
2316 };
2317
2318 MockRead data_reads1[] = {
2319 MockRead("HTTP/1.1 200 OK\r\n"
2320 "Connection: keep-alive\r\n"
2321 "Content-Length: 22\r\n\r\n"
2322 "This server is borked."),
2323 };
2324
2325 MockWrite data_writes2[] = {
2326 MockWrite("GET /foo HTTP/1.1\r\n"
2327 "Host: www.borked.com\r\n"
2328 "Connection: keep-alive\r\n\r\n"),
2329 };
2330
2331 MockRead data_reads2[] = {
2332 MockRead("HTTP/1.1 200 OK\r\n"
2333 "Content-Length: 3\r\n\r\n"
2334 "foo"),
2335 };
Ryan Sleevib8d7ea02018-05-07 20:01:012336 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132337 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012338 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132339 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2340
2341 TestCompletionCallback callback;
2342 HttpRequestInfo request1;
2343 request1.method = "HEAD";
2344 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102345 request1.traffic_annotation =
2346 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132347
bnc87dcefc2017-05-25 12:47:582348 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192349 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202350 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012351 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132352
2353 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2354 ASSERT_TRUE(response1);
2355 ASSERT_TRUE(response1->headers);
2356 EXPECT_EQ(200, response1->headers->response_code());
2357 EXPECT_TRUE(response1->headers->IsKeepAlive());
2358
2359 std::string response_data1;
robpercival214763f2016-07-01 23:27:012360 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132361 EXPECT_EQ("", response_data1);
2362 // Deleting the transaction attempts to release the socket back into the
2363 // socket pool.
2364 trans1.reset();
2365
2366 HttpRequestInfo request2;
2367 request2.method = "GET";
2368 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102369 request2.traffic_annotation =
2370 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132371
bnc87dcefc2017-05-25 12:47:582372 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192373 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202374 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012375 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132376
2377 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2378 ASSERT_TRUE(response2);
2379 ASSERT_TRUE(response2->headers);
2380 EXPECT_EQ(200, response2->headers->response_code());
2381
2382 std::string response_data2;
robpercival214763f2016-07-01 23:27:012383 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132384 EXPECT_EQ("foo", response_data2);
2385}
2386
bncd16676a2016-07-20 16:23:012387TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132388 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2389 MockWrite data_writes1[] = {
2390 MockWrite("GET / HTTP/1.1\r\n"
2391 "Host: www.borked.com\r\n"
2392 "Connection: keep-alive\r\n\r\n"),
2393 };
2394
2395 MockRead data_reads1[] = {
2396 MockRead("HTTP/1.1 200 OK\r\n"
2397 "Connection: keep-alive\r\n"
2398 "Content-Length: 22\r\n\r\n"
2399 "This server is borked."
2400 "Bonus data!"),
2401 };
2402
2403 MockWrite data_writes2[] = {
2404 MockWrite("GET /foo HTTP/1.1\r\n"
2405 "Host: www.borked.com\r\n"
2406 "Connection: keep-alive\r\n\r\n"),
2407 };
2408
2409 MockRead data_reads2[] = {
2410 MockRead("HTTP/1.1 200 OK\r\n"
2411 "Content-Length: 3\r\n\r\n"
2412 "foo"),
2413 };
Ryan Sleevib8d7ea02018-05-07 20:01:012414 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132415 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012416 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132417 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2418
2419 TestCompletionCallback callback;
2420 HttpRequestInfo request1;
2421 request1.method = "GET";
2422 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102423 request1.traffic_annotation =
2424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132425
bnc87dcefc2017-05-25 12:47:582426 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192427 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202428 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012429 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132430
2431 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2432 ASSERT_TRUE(response1);
2433 ASSERT_TRUE(response1->headers);
2434 EXPECT_EQ(200, response1->headers->response_code());
2435 EXPECT_TRUE(response1->headers->IsKeepAlive());
2436
2437 std::string response_data1;
robpercival214763f2016-07-01 23:27:012438 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132439 EXPECT_EQ("This server is borked.", response_data1);
2440 // Deleting the transaction attempts to release the socket back into the
2441 // socket pool.
2442 trans1.reset();
2443
2444 HttpRequestInfo request2;
2445 request2.method = "GET";
2446 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102447 request2.traffic_annotation =
2448 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132449
bnc87dcefc2017-05-25 12:47:582450 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192451 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202452 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012453 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132454
2455 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2456 ASSERT_TRUE(response2);
2457 ASSERT_TRUE(response2->headers);
2458 EXPECT_EQ(200, response2->headers->response_code());
2459
2460 std::string response_data2;
robpercival214763f2016-07-01 23:27:012461 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132462 EXPECT_EQ("foo", response_data2);
2463}
2464
bncd16676a2016-07-20 16:23:012465TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132466 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2467 MockWrite data_writes1[] = {
2468 MockWrite("GET / HTTP/1.1\r\n"
2469 "Host: www.borked.com\r\n"
2470 "Connection: keep-alive\r\n\r\n"),
2471 };
2472
2473 MockRead data_reads1[] = {
2474 MockRead("HTTP/1.1 200 OK\r\n"
2475 "Connection: keep-alive\r\n"
2476 "Transfer-Encoding: chunked\r\n\r\n"),
2477 MockRead("16\r\nThis server is borked.\r\n"),
2478 MockRead("0\r\n\r\nBonus data!"),
2479 };
2480
2481 MockWrite data_writes2[] = {
2482 MockWrite("GET /foo HTTP/1.1\r\n"
2483 "Host: www.borked.com\r\n"
2484 "Connection: keep-alive\r\n\r\n"),
2485 };
2486
2487 MockRead data_reads2[] = {
2488 MockRead("HTTP/1.1 200 OK\r\n"
2489 "Content-Length: 3\r\n\r\n"
2490 "foo"),
2491 };
Ryan Sleevib8d7ea02018-05-07 20:01:012492 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132493 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012494 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132495 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2496
2497 TestCompletionCallback callback;
2498 HttpRequestInfo request1;
2499 request1.method = "GET";
2500 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102501 request1.traffic_annotation =
2502 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132503
bnc87dcefc2017-05-25 12:47:582504 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192505 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202506 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012507 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132508
2509 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2510 ASSERT_TRUE(response1);
2511 ASSERT_TRUE(response1->headers);
2512 EXPECT_EQ(200, response1->headers->response_code());
2513 EXPECT_TRUE(response1->headers->IsKeepAlive());
2514
2515 std::string response_data1;
robpercival214763f2016-07-01 23:27:012516 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132517 EXPECT_EQ("This server is borked.", response_data1);
2518 // Deleting the transaction attempts to release the socket back into the
2519 // socket pool.
2520 trans1.reset();
2521
2522 HttpRequestInfo request2;
2523 request2.method = "GET";
2524 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102525 request2.traffic_annotation =
2526 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132527
bnc87dcefc2017-05-25 12:47:582528 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192529 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202530 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012531 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132532
2533 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2534 ASSERT_TRUE(response2);
2535 ASSERT_TRUE(response2->headers);
2536 EXPECT_EQ(200, response2->headers->response_code());
2537
2538 std::string response_data2;
robpercival214763f2016-07-01 23:27:012539 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132540 EXPECT_EQ("foo", response_data2);
2541}
2542
2543// This is a little different from the others - it tests the case that the
2544// HttpStreamParser doesn't know if there's extra data on a socket or not when
2545// the HttpNetworkTransaction is torn down, because the response body hasn't
2546// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012547TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132548 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2549 MockWrite data_writes1[] = {
2550 MockWrite("GET / HTTP/1.1\r\n"
2551 "Host: www.borked.com\r\n"
2552 "Connection: keep-alive\r\n\r\n"),
2553 };
2554
2555 MockRead data_reads1[] = {
2556 MockRead("HTTP/1.1 200 OK\r\n"
2557 "Connection: keep-alive\r\n"
2558 "Transfer-Encoding: chunked\r\n\r\n"),
2559 MockRead("16\r\nThis server is borked.\r\n"),
2560 MockRead("0\r\n\r\nBonus data!"),
2561 };
Ryan Sleevib8d7ea02018-05-07 20:01:012562 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2564
2565 TestCompletionCallback callback;
2566 HttpRequestInfo request1;
2567 request1.method = "GET";
2568 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102569 request1.traffic_annotation =
2570 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132571
bnc87dcefc2017-05-25 12:47:582572 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192573 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582574 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012575 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132576
bnc87dcefc2017-05-25 12:47:582577 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132578 ASSERT_TRUE(response1);
2579 ASSERT_TRUE(response1->headers);
2580 EXPECT_EQ(200, response1->headers->response_code());
2581 EXPECT_TRUE(response1->headers->IsKeepAlive());
2582
2583 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2584 // response body.
bnc87dcefc2017-05-25 12:47:582585 trans.reset();
mmenke5f94fda2016-06-02 20:54:132586
2587 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2588 // socket can't be reused, rather than returning it to the socket pool.
2589 base::RunLoop().RunUntilIdle();
2590
2591 // There should be no idle sockets in the pool.
2592 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2593}
2594
[email protected]038e9a32008-10-08 22:40:162595// Test the request-challenge-retry sequence for basic auth.
2596// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012597TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422598 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162599 request.method = "GET";
bncce36dca22015-04-21 22:11:232600 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102601 request.traffic_annotation =
2602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162603
Matt Muellerd9342e3a2019-11-26 01:41:142604 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072605 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092606 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162607 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272608
[email protected]f9ee6b52008-11-08 06:46:232609 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232610 MockWrite(
2611 "GET / HTTP/1.1\r\n"
2612 "Host: www.example.org\r\n"
2613 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232614 };
2615
[email protected]038e9a32008-10-08 22:40:162616 MockRead data_reads1[] = {
2617 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2618 // Give a couple authenticate options (only the middle one is actually
2619 // supported).
[email protected]22927ad2009-09-21 19:56:192620 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162621 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2622 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2623 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2624 // Large content-length -- won't matter, as connection will be reset.
2625 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062626 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162627 };
2628
2629 // After calling trans->RestartWithAuth(), this is the request we should
2630 // be issuing -- the final header line contains the credentials.
2631 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232632 MockWrite(
2633 "GET / HTTP/1.1\r\n"
2634 "Host: www.example.org\r\n"
2635 "Connection: keep-alive\r\n"
2636 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162637 };
2638
2639 // Lastly, the server responds with the actual content.
2640 MockRead data_reads2[] = {
2641 MockRead("HTTP/1.0 200 OK\r\n"),
2642 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2643 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062644 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162645 };
2646
Ryan Sleevib8d7ea02018-05-07 20:01:012647 StaticSocketDataProvider data1(data_reads1, data_writes1);
2648 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072649 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2650 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162651
[email protected]49639fa2011-12-20 23:22:412652 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162653
tfarina42834112016-09-22 13:38:202654 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012655 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162656
2657 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012658 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162659
[email protected]58e32bb2013-01-21 18:23:252660 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162661 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252662 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2663
Ryan Sleevib8d7ea02018-05-07 20:01:012664 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162665 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012666 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162667 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192668
bnc691fda62016-08-12 00:43:162669 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522670 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582671 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162672
[email protected]49639fa2011-12-20 23:22:412673 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162674
bnc691fda62016-08-12 00:43:162675 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162677
2678 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012679 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162680
[email protected]58e32bb2013-01-21 18:23:252681 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162682 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252683 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2684 // The load timing after restart should have a new socket ID, and times after
2685 // those of the first load timing.
2686 EXPECT_LE(load_timing_info1.receive_headers_end,
2687 load_timing_info2.connect_timing.connect_start);
2688 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2689
Ryan Sleevib8d7ea02018-05-07 20:01:012690 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162691 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012692 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162693 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192694
bnc691fda62016-08-12 00:43:162695 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522696 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582697 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162698 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162699}
2700
ttuttled9dbc652015-09-29 20:00:592701// Test the request-challenge-retry sequence for basic auth.
2702// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012703TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592704 HttpRequestInfo request;
2705 request.method = "GET";
2706 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102707 request.traffic_annotation =
2708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592709
Matt Muellerd9342e3a2019-11-26 01:41:142710 RecordingTestNetLog log;
ttuttled9dbc652015-09-29 20:00:592711 MockHostResolver* resolver = new MockHostResolver();
2712 session_deps_.net_log = &log;
2713 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092714 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162715 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592716
2717 resolver->rules()->ClearRules();
2718 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2719
2720 MockWrite data_writes1[] = {
2721 MockWrite("GET / HTTP/1.1\r\n"
2722 "Host: www.example.org\r\n"
2723 "Connection: keep-alive\r\n\r\n"),
2724 };
2725
2726 MockRead data_reads1[] = {
2727 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2728 // Give a couple authenticate options (only the middle one is actually
2729 // supported).
2730 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2731 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2732 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2734 // Large content-length -- won't matter, as connection will be reset.
2735 MockRead("Content-Length: 10000\r\n\r\n"),
2736 MockRead(SYNCHRONOUS, ERR_FAILED),
2737 };
2738
2739 // After calling trans->RestartWithAuth(), this is the request we should
2740 // be issuing -- the final header line contains the credentials.
2741 MockWrite data_writes2[] = {
2742 MockWrite("GET / HTTP/1.1\r\n"
2743 "Host: www.example.org\r\n"
2744 "Connection: keep-alive\r\n"
2745 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2746 };
2747
2748 // Lastly, the server responds with the actual content.
2749 MockRead data_reads2[] = {
2750 MockRead("HTTP/1.0 200 OK\r\n"),
2751 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2752 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2753 };
2754
Ryan Sleevib8d7ea02018-05-07 20:01:012755 StaticSocketDataProvider data1(data_reads1, data_writes1);
2756 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592757 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2758 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2759
2760 TestCompletionCallback callback1;
2761
bnc691fda62016-08-12 00:43:162762 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202763 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592764
2765 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162766 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592767 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2768
Ryan Sleevib8d7ea02018-05-07 20:01:012769 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162770 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012771 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162772 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592773
bnc691fda62016-08-12 00:43:162774 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592775 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582776 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592777
2778 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162779 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592780 ASSERT_FALSE(endpoint.address().empty());
2781 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2782
2783 resolver->rules()->ClearRules();
2784 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2785
2786 TestCompletionCallback callback2;
2787
bnc691fda62016-08-12 00:43:162788 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592789 AuthCredentials(kFoo, kBar), callback2.callback())));
2790
2791 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162792 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592793 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2794 // The load timing after restart should have a new socket ID, and times after
2795 // those of the first load timing.
2796 EXPECT_LE(load_timing_info1.receive_headers_end,
2797 load_timing_info2.connect_timing.connect_start);
2798 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2799
Ryan Sleevib8d7ea02018-05-07 20:01:012800 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162801 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012802 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162803 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592804
bnc691fda62016-08-12 00:43:162805 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592806 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582807 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592808 EXPECT_EQ(100, response->headers->GetContentLength());
2809
bnc691fda62016-08-12 00:43:162810 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592811 ASSERT_FALSE(endpoint.address().empty());
2812 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2813}
2814
David Benjamin83ddfb32018-03-30 01:07:522815// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2816// will eventually give up.
2817TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2818 HttpRequestInfo request;
2819 request.method = "GET";
2820 request.url = GURL("http://www.example.org/");
2821 request.traffic_annotation =
2822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2823
Matt Muellerd9342e3a2019-11-26 01:41:142824 RecordingTestNetLog log;
David Benjamin83ddfb32018-03-30 01:07:522825 session_deps_.net_log = &log;
2826 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2827 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2828
2829 MockWrite data_writes[] = {
2830 MockWrite("GET / HTTP/1.1\r\n"
2831 "Host: www.example.org\r\n"
2832 "Connection: keep-alive\r\n\r\n"),
2833 };
2834
2835 MockRead data_reads[] = {
2836 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2837 // Give a couple authenticate options (only the middle one is actually
2838 // supported).
2839 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2840 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2841 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2842 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2843 // Large content-length -- won't matter, as connection will be reset.
2844 MockRead("Content-Length: 10000\r\n\r\n"),
2845 MockRead(SYNCHRONOUS, ERR_FAILED),
2846 };
2847
2848 // After calling trans->RestartWithAuth(), this is the request we should
2849 // be issuing -- the final header line contains the credentials.
2850 MockWrite data_writes_restart[] = {
2851 MockWrite("GET / HTTP/1.1\r\n"
2852 "Host: www.example.org\r\n"
2853 "Connection: keep-alive\r\n"
2854 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2855 };
2856
Ryan Sleevib8d7ea02018-05-07 20:01:012857 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522858 session_deps_.socket_factory->AddSocketDataProvider(&data);
2859
2860 TestCompletionCallback callback;
2861 int rv = callback.GetResult(
2862 trans.Start(&request, callback.callback(), NetLogWithSource()));
2863
2864 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2865 for (int i = 0; i < 32; i++) {
2866 // Check the previous response was a 401.
2867 EXPECT_THAT(rv, IsOk());
2868 const HttpResponseInfo* response = trans.GetResponseInfo();
2869 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582870 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522871
2872 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012873 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522874 session_deps_.socket_factory->AddSocketDataProvider(
2875 data_restarts.back().get());
2876 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2877 callback.callback()));
2878 }
2879
2880 // After too many tries, the transaction should have given up.
2881 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2882}
2883
bncd16676a2016-07-20 16:23:012884TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462885 HttpRequestInfo request;
2886 request.method = "GET";
bncce36dca22015-04-21 22:11:232887 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292888 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:102889 request.traffic_annotation =
2890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462891
danakj1fd259a02016-04-16 03:17:092892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162893 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272894
[email protected]861fcd52009-08-26 02:33:462895 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232896 MockWrite(
2897 "GET / HTTP/1.1\r\n"
2898 "Host: www.example.org\r\n"
2899 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462900 };
2901
2902 MockRead data_reads[] = {
2903 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2904 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2906 // Large content-length -- won't matter, as connection will be reset.
2907 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062908 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462909 };
2910
Ryan Sleevib8d7ea02018-05-07 20:01:012911 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072912 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412913 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462914
tfarina42834112016-09-22 13:38:202915 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462917
2918 rv = callback.WaitForResult();
2919 EXPECT_EQ(0, rv);
2920
Ryan Sleevib8d7ea02018-05-07 20:01:012921 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162922 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012923 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162924 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192925
bnc691fda62016-08-12 00:43:162926 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522927 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582928 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462929}
2930
[email protected]2d2697f92009-02-18 21:00:322931// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2932// connection.
bncd16676a2016-07-20 16:23:012933TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182934 // On the second pass, the body read of the auth challenge is synchronous, so
2935 // IsConnectedAndIdle returns false. The socket should still be drained and
2936 // reused. See http://crbug.com/544255.
2937 for (int i = 0; i < 2; ++i) {
2938 HttpRequestInfo request;
2939 request.method = "GET";
2940 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102941 request.traffic_annotation =
2942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322943
Matt Muellerd9342e3a2019-11-26 01:41:142944 RecordingTestNetLog log;
mmenkecc2298e2015-12-07 18:20:182945 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092946 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272947
mmenkecc2298e2015-12-07 18:20:182948 MockWrite data_writes[] = {
2949 MockWrite(ASYNC, 0,
2950 "GET / HTTP/1.1\r\n"
2951 "Host: www.example.org\r\n"
2952 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322953
bnc691fda62016-08-12 00:43:162954 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182955 // be issuing -- the final header line contains the credentials.
2956 MockWrite(ASYNC, 6,
2957 "GET / HTTP/1.1\r\n"
2958 "Host: www.example.org\r\n"
2959 "Connection: keep-alive\r\n"
2960 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2961 };
[email protected]2d2697f92009-02-18 21:00:322962
mmenkecc2298e2015-12-07 18:20:182963 MockRead data_reads[] = {
2964 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2965 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2966 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2967 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2968 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322969
mmenkecc2298e2015-12-07 18:20:182970 // Lastly, the server responds with the actual content.
2971 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2972 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2973 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2974 MockRead(ASYNC, 10, "Hello"),
2975 };
[email protected]2d2697f92009-02-18 21:00:322976
Ryan Sleevib8d7ea02018-05-07 20:01:012977 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182978 data.set_busy_before_sync_reads(true);
2979 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462980
mmenkecc2298e2015-12-07 18:20:182981 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322982
bnc691fda62016-08-12 00:43:162983 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202984 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012985 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322986
mmenkecc2298e2015-12-07 18:20:182987 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162988 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182989 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322990
bnc691fda62016-08-12 00:43:162991 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182992 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582993 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322994
mmenkecc2298e2015-12-07 18:20:182995 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252996
bnc691fda62016-08-12 00:43:162997 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2998 callback2.callback());
robpercival214763f2016-07-01 23:27:012999 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323000
mmenkecc2298e2015-12-07 18:20:183001 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163002 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183003 TestLoadTimingReused(load_timing_info2);
3004 // The load timing after restart should have the same socket ID, and times
3005 // those of the first load timing.
3006 EXPECT_LE(load_timing_info1.receive_headers_end,
3007 load_timing_info2.send_start);
3008 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323009
bnc691fda62016-08-12 00:43:163010 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183011 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583012 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183013 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323014
mmenkecc2298e2015-12-07 18:20:183015 std::string response_data;
bnc691fda62016-08-12 00:43:163016 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323017
Ryan Sleevib8d7ea02018-05-07 20:01:013018 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163019 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013020 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163021 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183022 }
[email protected]2d2697f92009-02-18 21:00:323023}
3024
3025// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3026// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013027TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423028 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323029 request.method = "GET";
bncce36dca22015-04-21 22:11:233030 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103031 request.traffic_annotation =
3032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323033
danakj1fd259a02016-04-16 03:17:093034 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273035
[email protected]2d2697f92009-02-18 21:00:323036 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163037 MockWrite("GET / HTTP/1.1\r\n"
3038 "Host: www.example.org\r\n"
3039 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323040
bnc691fda62016-08-12 00:43:163041 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233042 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163043 MockWrite("GET / HTTP/1.1\r\n"
3044 "Host: www.example.org\r\n"
3045 "Connection: keep-alive\r\n"
3046 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323047 };
3048
[email protected]2d2697f92009-02-18 21:00:323049 MockRead data_reads1[] = {
3050 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3051 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313052 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323053
3054 // Lastly, the server responds with the actual content.
3055 MockRead("HTTP/1.1 200 OK\r\n"),
3056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503057 MockRead("Content-Length: 5\r\n\r\n"),
3058 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323059 };
3060
[email protected]2d0a4f92011-05-05 16:38:463061 // An incorrect reconnect would cause this to be read.
3062 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063063 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463064 };
3065
Ryan Sleevib8d7ea02018-05-07 20:01:013066 StaticSocketDataProvider data1(data_reads1, data_writes1);
3067 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3069 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323070
[email protected]49639fa2011-12-20 23:22:413071 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323072
bnc691fda62016-08-12 00:43:163073 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203074 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323076
3077 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013078 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323079
bnc691fda62016-08-12 00:43:163080 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523081 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583082 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323083
[email protected]49639fa2011-12-20 23:22:413084 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323085
bnc691fda62016-08-12 00:43:163086 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013087 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323088
3089 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013090 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323091
bnc691fda62016-08-12 00:43:163092 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523093 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583094 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503095 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323096}
3097
3098// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3099// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013100TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423101 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323102 request.method = "GET";
bncce36dca22015-04-21 22:11:233103 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103104 request.traffic_annotation =
3105 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323106
danakj1fd259a02016-04-16 03:17:093107 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273108
[email protected]2d2697f92009-02-18 21:00:323109 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163110 MockWrite("GET / HTTP/1.1\r\n"
3111 "Host: www.example.org\r\n"
3112 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323113
bnc691fda62016-08-12 00:43:163114 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233115 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163116 MockWrite("GET / HTTP/1.1\r\n"
3117 "Host: www.example.org\r\n"
3118 "Connection: keep-alive\r\n"
3119 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323120 };
3121
3122 // Respond with 5 kb of response body.
3123 std::string large_body_string("Unauthorized");
3124 large_body_string.append(5 * 1024, ' ');
3125 large_body_string.append("\r\n");
3126
3127 MockRead data_reads1[] = {
3128 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3129 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3130 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3131 // 5134 = 12 + 5 * 1024 + 2
3132 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063133 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323134
3135 // Lastly, the server responds with the actual content.
3136 MockRead("HTTP/1.1 200 OK\r\n"),
3137 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503138 MockRead("Content-Length: 5\r\n\r\n"),
3139 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323140 };
3141
[email protected]2d0a4f92011-05-05 16:38:463142 // An incorrect reconnect would cause this to be read.
3143 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063144 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463145 };
3146
Ryan Sleevib8d7ea02018-05-07 20:01:013147 StaticSocketDataProvider data1(data_reads1, data_writes1);
3148 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073149 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3150 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323151
[email protected]49639fa2011-12-20 23:22:413152 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323153
bnc691fda62016-08-12 00:43:163154 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203155 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323157
3158 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013159 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323160
bnc691fda62016-08-12 00:43:163161 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523162 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583163 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323164
[email protected]49639fa2011-12-20 23:22:413165 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323166
bnc691fda62016-08-12 00:43:163167 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013168 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323169
3170 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013171 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323172
bnc691fda62016-08-12 00:43:163173 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523174 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583175 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503176 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323177}
3178
3179// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313180// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013181TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313182 HttpRequestInfo request;
3183 request.method = "GET";
bncce36dca22015-04-21 22:11:233184 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103185 request.traffic_annotation =
3186 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313187
danakj1fd259a02016-04-16 03:17:093188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273189
[email protected]11203f012009-11-12 23:02:313190 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233191 MockWrite(
3192 "GET / HTTP/1.1\r\n"
3193 "Host: www.example.org\r\n"
3194 "Connection: keep-alive\r\n\r\n"),
3195 // This simulates the seemingly successful write to a closed connection
3196 // if the bug is not fixed.
3197 MockWrite(
3198 "GET / HTTP/1.1\r\n"
3199 "Host: www.example.org\r\n"
3200 "Connection: keep-alive\r\n"
3201 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313202 };
3203
3204 MockRead data_reads1[] = {
3205 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3206 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3207 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3208 MockRead("Content-Length: 14\r\n\r\n"),
3209 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063210 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313211 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063212 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313213 };
3214
bnc691fda62016-08-12 00:43:163215 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313216 // be issuing -- the final header line contains the credentials.
3217 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233218 MockWrite(
3219 "GET / HTTP/1.1\r\n"
3220 "Host: www.example.org\r\n"
3221 "Connection: keep-alive\r\n"
3222 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313223 };
3224
3225 // Lastly, the server responds with the actual content.
3226 MockRead data_reads2[] = {
3227 MockRead("HTTP/1.1 200 OK\r\n"),
3228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503229 MockRead("Content-Length: 5\r\n\r\n"),
3230 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313231 };
3232
Ryan Sleevib8d7ea02018-05-07 20:01:013233 StaticSocketDataProvider data1(data_reads1, data_writes1);
3234 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073235 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3236 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313237
[email protected]49639fa2011-12-20 23:22:413238 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313239
bnc691fda62016-08-12 00:43:163240 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203241 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013242 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313243
3244 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013245 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313246
bnc691fda62016-08-12 00:43:163247 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523248 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583249 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313250
[email protected]49639fa2011-12-20 23:22:413251 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313252
bnc691fda62016-08-12 00:43:163253 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013254 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313255
3256 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013257 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313258
bnc691fda62016-08-12 00:43:163259 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523260 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583261 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503262 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313263}
3264
[email protected]394816e92010-08-03 07:38:593265// Test the request-challenge-retry sequence for basic auth, over a connection
3266// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013267TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013268 HttpRequestInfo request;
3269 request.method = "GET";
bncce36dca22015-04-21 22:11:233270 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013271 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293272 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103273 request.traffic_annotation =
3274 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013275
3276 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593277 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563278 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493279 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143280 RecordingBoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013281 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093282 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013283
3284 // Since we have proxy, should try to establish tunnel.
3285 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543286 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173287 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543288 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013289 };
3290
mmenkee71e15332015-10-07 16:39:543291 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013292 // connection.
3293 MockRead data_reads1[] = {
3294 // No credentials.
3295 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3296 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543297 };
ttuttle34f63b52015-03-05 04:33:013298
mmenkee71e15332015-10-07 16:39:543299 // Since the first connection couldn't be reused, need to establish another
3300 // once given credentials.
3301 MockWrite data_writes2[] = {
3302 // After calling trans->RestartWithAuth(), this is the request we should
3303 // be issuing -- the final header line contains the credentials.
3304 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173305 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543306 "Proxy-Connection: keep-alive\r\n"
3307 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3308
3309 MockWrite("GET / HTTP/1.1\r\n"
3310 "Host: www.example.org\r\n"
3311 "Connection: keep-alive\r\n\r\n"),
3312 };
3313
3314 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013315 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3316
3317 MockRead("HTTP/1.1 200 OK\r\n"),
3318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3319 MockRead("Content-Length: 5\r\n\r\n"),
3320 MockRead(SYNCHRONOUS, "hello"),
3321 };
3322
Ryan Sleevib8d7ea02018-05-07 20:01:013323 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013324 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013325 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543326 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013327 SSLSocketDataProvider ssl(ASYNC, OK);
3328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3329
3330 TestCompletionCallback callback1;
3331
bnc87dcefc2017-05-25 12:47:583332 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193333 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013334
3335 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013336 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013337
3338 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013339 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543340 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013341 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003342 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3343 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013344 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003345 entries, pos,
3346 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3347 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013348
3349 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523350 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013351 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523352 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013353 EXPECT_EQ(407, response->headers->response_code());
3354 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583355 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013356
3357 LoadTimingInfo load_timing_info;
3358 // CONNECT requests and responses are handled at the connect job level, so
3359 // the transaction does not yet have a connection.
3360 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3361
3362 TestCompletionCallback callback2;
3363
3364 rv =
3365 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013366 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013367
3368 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013369 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013370
3371 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523372 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013373
3374 EXPECT_TRUE(response->headers->IsKeepAlive());
3375 EXPECT_EQ(200, response->headers->response_code());
3376 EXPECT_EQ(5, response->headers->GetContentLength());
3377 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3378
Matt Menke96092e62019-10-18 04:09:333379 // Check that credentials were successfully cached, with the right target.
3380 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3381 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263382 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333383 ASSERT_TRUE(entry);
3384 ASSERT_EQ(kFoo, entry->credentials().username());
3385 ASSERT_EQ(kBar, entry->credentials().password());
3386
ttuttle34f63b52015-03-05 04:33:013387 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583388 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013389
3390 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3391 TestLoadTimingNotReusedWithPac(load_timing_info,
3392 CONNECT_TIMING_HAS_SSL_TIMES);
3393
3394 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113395 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle34f63b52015-03-05 04:33:013396}
3397
3398// Test the request-challenge-retry sequence for basic auth, over a connection
3399// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013400TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593401 HttpRequestInfo request;
3402 request.method = "GET";
bncce36dca22015-04-21 22:11:233403 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593404 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293405 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103406 request.traffic_annotation =
3407 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593408
[email protected]cb9bf6ca2011-01-28 13:15:273409 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593410 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563411 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493412 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143413 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073414 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093415 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273416
[email protected]394816e92010-08-03 07:38:593417 // Since we have proxy, should try to establish tunnel.
3418 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543419 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173420 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543421 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113422 };
3423
mmenkee71e15332015-10-07 16:39:543424 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083425 // connection.
3426 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543427 // No credentials.
3428 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3429 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3430 MockRead("Proxy-Connection: close\r\n\r\n"),
3431 };
mmenkee0b5c882015-08-26 20:29:113432
mmenkee71e15332015-10-07 16:39:543433 MockWrite data_writes2[] = {
3434 // After calling trans->RestartWithAuth(), this is the request we should
3435 // be issuing -- the final header line contains the credentials.
3436 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173437 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543438 "Proxy-Connection: keep-alive\r\n"
3439 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083440
mmenkee71e15332015-10-07 16:39:543441 MockWrite("GET / HTTP/1.1\r\n"
3442 "Host: www.example.org\r\n"
3443 "Connection: keep-alive\r\n\r\n"),
3444 };
3445
3446 MockRead data_reads2[] = {
3447 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3448
3449 MockRead("HTTP/1.1 200 OK\r\n"),
3450 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3451 MockRead("Content-Length: 5\r\n\r\n"),
3452 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593453 };
3454
Ryan Sleevib8d7ea02018-05-07 20:01:013455 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073456 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013457 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543458 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063459 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593461
[email protected]49639fa2011-12-20 23:22:413462 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593463
bnc87dcefc2017-05-25 12:47:583464 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193465 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503466
[email protected]49639fa2011-12-20 23:22:413467 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013468 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593469
3470 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013471 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543472 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593473 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003474 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3475 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593476 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403477 entries, pos,
mikecirone8b85c432016-09-08 19:11:003478 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3479 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593480
3481 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523482 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013483 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523484 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593485 EXPECT_EQ(407, response->headers->response_code());
3486 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583487 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593488
[email protected]029c83b62013-01-24 05:28:203489 LoadTimingInfo load_timing_info;
3490 // CONNECT requests and responses are handled at the connect job level, so
3491 // the transaction does not yet have a connection.
3492 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3493
[email protected]49639fa2011-12-20 23:22:413494 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593495
[email protected]49639fa2011-12-20 23:22:413496 rv = trans->RestartWithAuth(
3497 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013498 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593499
3500 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013501 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593502
3503 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523504 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593505
3506 EXPECT_TRUE(response->headers->IsKeepAlive());
3507 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503508 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593509 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3510
3511 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583512 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503513
[email protected]029c83b62013-01-24 05:28:203514 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3515 TestLoadTimingNotReusedWithPac(load_timing_info,
3516 CONNECT_TIMING_HAS_SSL_TIMES);
3517
[email protected]0b0bf032010-09-21 18:08:503518 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113519 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]394816e92010-08-03 07:38:593520}
3521
[email protected]11203f012009-11-12 23:02:313522// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013523// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013524TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233525 // On the second pass, the body read of the auth challenge is synchronous, so
3526 // IsConnectedAndIdle returns false. The socket should still be drained and
3527 // reused. See http://crbug.com/544255.
3528 for (int i = 0; i < 2; ++i) {
3529 HttpRequestInfo request;
3530 request.method = "GET";
3531 request.url = GURL("https://www.example.org/");
3532 // Ensure that proxy authentication is attempted even
3533 // when the no authentication data flag is set.
3534 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103535 request.traffic_annotation =
3536 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013537
mmenked39192ee2015-12-09 00:57:233538 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593539 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563540 ConfiguredProxyResolutionService::CreateFixed(
3541 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143542 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233543 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093544 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013545
bnc691fda62016-08-12 00:43:163546 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013547
mmenked39192ee2015-12-09 00:57:233548 // Since we have proxy, should try to establish tunnel.
3549 MockWrite data_writes1[] = {
3550 MockWrite(ASYNC, 0,
3551 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3552 "Host: www.example.org:443\r\n"
3553 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013554
bnc691fda62016-08-12 00:43:163555 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233556 // be issuing -- the final header line contains the credentials.
3557 MockWrite(ASYNC, 3,
3558 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3559 "Host: www.example.org:443\r\n"
3560 "Proxy-Connection: keep-alive\r\n"
3561 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3562 };
ttuttle34f63b52015-03-05 04:33:013563
mmenked39192ee2015-12-09 00:57:233564 // The proxy responds to the connect with a 407, using a persistent
3565 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3566 MockRead data_reads1[] = {
3567 // No credentials.
3568 MockRead(ASYNC, 1,
3569 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3570 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3571 "Proxy-Connection: keep-alive\r\n"
3572 "Content-Length: 10\r\n\r\n"),
3573 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013574
mmenked39192ee2015-12-09 00:57:233575 // Wrong credentials (wrong password).
3576 MockRead(ASYNC, 4,
3577 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3578 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3579 "Proxy-Connection: keep-alive\r\n"
3580 "Content-Length: 10\r\n\r\n"),
3581 // No response body because the test stops reading here.
3582 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3583 };
ttuttle34f63b52015-03-05 04:33:013584
Ryan Sleevib8d7ea02018-05-07 20:01:013585 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233586 data1.set_busy_before_sync_reads(true);
3587 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013588
mmenked39192ee2015-12-09 00:57:233589 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013590
bnc691fda62016-08-12 00:43:163591 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013592 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013593
Eric Roman79cc7552019-07-19 02:17:543594 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233595 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003596 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3597 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233598 ExpectLogContainsSomewhere(
3599 entries, pos,
mikecirone8b85c432016-09-08 19:11:003600 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3601 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013602
bnc691fda62016-08-12 00:43:163603 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233604 ASSERT_TRUE(response);
3605 ASSERT_TRUE(response->headers);
3606 EXPECT_TRUE(response->headers->IsKeepAlive());
3607 EXPECT_EQ(407, response->headers->response_code());
3608 EXPECT_EQ(10, response->headers->GetContentLength());
3609 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583610 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013611
mmenked39192ee2015-12-09 00:57:233612 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013613
mmenked39192ee2015-12-09 00:57:233614 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163615 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3616 callback2.callback());
robpercival214763f2016-07-01 23:27:013617 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013618
bnc691fda62016-08-12 00:43:163619 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233620 ASSERT_TRUE(response);
3621 ASSERT_TRUE(response->headers);
3622 EXPECT_TRUE(response->headers->IsKeepAlive());
3623 EXPECT_EQ(407, response->headers->response_code());
3624 EXPECT_EQ(10, response->headers->GetContentLength());
3625 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583626 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013627
mmenked39192ee2015-12-09 00:57:233628 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3629 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113630 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233631 }
ttuttle34f63b52015-03-05 04:33:013632}
3633
3634// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3635// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013636TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233637 // On the second pass, the body read of the auth challenge is synchronous, so
3638 // IsConnectedAndIdle returns false. The socket should still be drained and
3639 // reused. See http://crbug.com/544255.
3640 for (int i = 0; i < 2; ++i) {
3641 HttpRequestInfo request;
3642 request.method = "GET";
3643 request.url = GURL("https://www.example.org/");
3644 // Ensure that proxy authentication is attempted even
3645 // when the no authentication data flag is set.
3646 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103647 request.traffic_annotation =
3648 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233649
3650 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593651 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563652 ConfiguredProxyResolutionService::CreateFixed(
3653 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143654 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233655 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093656 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233657
bnc691fda62016-08-12 00:43:163658 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233659
3660 // Since we have proxy, should try to establish tunnel.
3661 MockWrite data_writes1[] = {
3662 MockWrite(ASYNC, 0,
3663 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3664 "Host: www.example.org:443\r\n"
3665 "Proxy-Connection: keep-alive\r\n\r\n"),
3666
bnc691fda62016-08-12 00:43:163667 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233668 // be issuing -- the final header line contains the credentials.
3669 MockWrite(ASYNC, 3,
3670 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3671 "Host: www.example.org:443\r\n"
3672 "Proxy-Connection: keep-alive\r\n"
3673 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3674 };
3675
3676 // The proxy responds to the connect with a 407, using a persistent
3677 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3678 MockRead data_reads1[] = {
3679 // No credentials.
3680 MockRead(ASYNC, 1,
3681 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3682 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3683 "Content-Length: 10\r\n\r\n"),
3684 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3685
3686 // Wrong credentials (wrong password).
3687 MockRead(ASYNC, 4,
3688 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3689 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3690 "Content-Length: 10\r\n\r\n"),
3691 // No response body because the test stops reading here.
3692 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3693 };
3694
Ryan Sleevib8d7ea02018-05-07 20:01:013695 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233696 data1.set_busy_before_sync_reads(true);
3697 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3698
3699 TestCompletionCallback callback1;
3700
bnc691fda62016-08-12 00:43:163701 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013702 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233703
Eric Roman79cc7552019-07-19 02:17:543704 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233705 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003706 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3707 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233708 ExpectLogContainsSomewhere(
3709 entries, pos,
mikecirone8b85c432016-09-08 19:11:003710 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3711 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233712
bnc691fda62016-08-12 00:43:163713 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233714 ASSERT_TRUE(response);
3715 ASSERT_TRUE(response->headers);
3716 EXPECT_TRUE(response->headers->IsKeepAlive());
3717 EXPECT_EQ(407, response->headers->response_code());
3718 EXPECT_EQ(10, response->headers->GetContentLength());
3719 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583720 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503721 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233722
3723 TestCompletionCallback callback2;
3724
3725 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163726 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3727 callback2.callback());
robpercival214763f2016-07-01 23:27:013728 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233729
bnc691fda62016-08-12 00:43:163730 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233731 ASSERT_TRUE(response);
3732 ASSERT_TRUE(response->headers);
3733 EXPECT_TRUE(response->headers->IsKeepAlive());
3734 EXPECT_EQ(407, response->headers->response_code());
3735 EXPECT_EQ(10, response->headers->GetContentLength());
3736 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583737 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503738 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233739
3740 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3741 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113742 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233743 }
3744}
3745
3746// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3747// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3748// the case the server sends extra data on the original socket, so it can't be
3749// reused.
bncd16676a2016-07-20 16:23:013750TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273751 HttpRequestInfo request;
3752 request.method = "GET";
bncce36dca22015-04-21 22:11:233753 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273754 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293755 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103756 request.traffic_annotation =
3757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273758
[email protected]2d2697f92009-02-18 21:00:323759 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593760 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563761 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493762 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143763 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073764 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093765 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323766
[email protected]2d2697f92009-02-18 21:00:323767 // Since we have proxy, should try to establish tunnel.
3768 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233769 MockWrite(ASYNC, 0,
3770 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173771 "Host: www.example.org:443\r\n"
3772 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233773 };
[email protected]2d2697f92009-02-18 21:00:323774
mmenked39192ee2015-12-09 00:57:233775 // The proxy responds to the connect with a 407, using a persistent, but sends
3776 // extra data, so the socket cannot be reused.
3777 MockRead data_reads1[] = {
3778 // No credentials.
3779 MockRead(ASYNC, 1,
3780 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3781 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3782 "Content-Length: 10\r\n\r\n"),
3783 MockRead(SYNCHRONOUS, 2, "0123456789"),
3784 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3785 };
3786
3787 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233788 // After calling trans->RestartWithAuth(), this is the request we should
3789 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233790 MockWrite(ASYNC, 0,
3791 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173792 "Host: www.example.org:443\r\n"
3793 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233794 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3795
3796 MockWrite(ASYNC, 2,
3797 "GET / HTTP/1.1\r\n"
3798 "Host: www.example.org\r\n"
3799 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323800 };
3801
mmenked39192ee2015-12-09 00:57:233802 MockRead data_reads2[] = {
3803 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323804
mmenked39192ee2015-12-09 00:57:233805 MockRead(ASYNC, 3,
3806 "HTTP/1.1 200 OK\r\n"
3807 "Content-Type: text/html; charset=iso-8859-1\r\n"
3808 "Content-Length: 5\r\n\r\n"),
3809 // No response body because the test stops reading here.
3810 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323811 };
3812
Ryan Sleevib8d7ea02018-05-07 20:01:013813 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233814 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073815 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013816 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233817 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3818 SSLSocketDataProvider ssl(ASYNC, OK);
3819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323820
[email protected]49639fa2011-12-20 23:22:413821 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323822
bnc87dcefc2017-05-25 12:47:583823 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193824 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323825
mmenked39192ee2015-12-09 00:57:233826 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013827 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233828
Eric Roman79cc7552019-07-19 02:17:543829 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393830 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003831 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3832 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393833 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403834 entries, pos,
mikecirone8b85c432016-09-08 19:11:003835 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3836 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323837
[email protected]1c773ea12009-04-28 19:58:423838 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243839 ASSERT_TRUE(response);
3840 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323841 EXPECT_TRUE(response->headers->IsKeepAlive());
3842 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423843 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583844 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323845
mmenked39192ee2015-12-09 00:57:233846 LoadTimingInfo load_timing_info;
3847 // CONNECT requests and responses are handled at the connect job level, so
3848 // the transaction does not yet have a connection.
3849 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3850
[email protected]49639fa2011-12-20 23:22:413851 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323852
mmenked39192ee2015-12-09 00:57:233853 rv =
3854 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013855 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323856
[email protected]2d2697f92009-02-18 21:00:323857 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233858 EXPECT_EQ(200, response->headers->response_code());
3859 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423860 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133861
mmenked39192ee2015-12-09 00:57:233862 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583863 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233864
3865 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3866 TestLoadTimingNotReusedWithPac(load_timing_info,
3867 CONNECT_TIMING_HAS_SSL_TIMES);
3868
3869 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113870 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]2d2697f92009-02-18 21:00:323871}
3872
mmenkee71e15332015-10-07 16:39:543873// Test the case a proxy closes a socket while the challenge body is being
3874// drained.
bncd16676a2016-07-20 16:23:013875TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543876 HttpRequestInfo request;
3877 request.method = "GET";
3878 request.url = GURL("https://www.example.org/");
3879 // Ensure that proxy authentication is attempted even
3880 // when the no authentication data flag is set.
3881 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103882 request.traffic_annotation =
3883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543884
3885 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:563886 session_deps_.proxy_resolution_service =
3887 ConfiguredProxyResolutionService::CreateFixed(
3888 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093889 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543890
bnc691fda62016-08-12 00:43:163891 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543892
3893 // Since we have proxy, should try to establish tunnel.
3894 MockWrite data_writes1[] = {
3895 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173896 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543897 "Proxy-Connection: keep-alive\r\n\r\n"),
3898 };
3899
3900 // The proxy responds to the connect with a 407, using a persistent
3901 // connection.
3902 MockRead data_reads1[] = {
3903 // No credentials.
3904 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3905 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3906 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3907 // Server hands up in the middle of the body.
3908 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3909 };
3910
3911 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163912 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543913 // be issuing -- the final header line contains the credentials.
3914 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173915 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543916 "Proxy-Connection: keep-alive\r\n"
3917 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3918
3919 MockWrite("GET / HTTP/1.1\r\n"
3920 "Host: www.example.org\r\n"
3921 "Connection: keep-alive\r\n\r\n"),
3922 };
3923
3924 MockRead data_reads2[] = {
3925 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3926
3927 MockRead("HTTP/1.1 200 OK\r\n"),
3928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3929 MockRead("Content-Length: 5\r\n\r\n"),
3930 MockRead(SYNCHRONOUS, "hello"),
3931 };
3932
Ryan Sleevib8d7ea02018-05-07 20:01:013933 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543934 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013935 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543936 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3937 SSLSocketDataProvider ssl(ASYNC, OK);
3938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3939
3940 TestCompletionCallback callback;
3941
tfarina42834112016-09-22 13:38:203942 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013943 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543944
bnc691fda62016-08-12 00:43:163945 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543946 ASSERT_TRUE(response);
3947 ASSERT_TRUE(response->headers);
3948 EXPECT_TRUE(response->headers->IsKeepAlive());
3949 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583950 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543951
bnc691fda62016-08-12 00:43:163952 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013953 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543954
bnc691fda62016-08-12 00:43:163955 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543956 ASSERT_TRUE(response);
3957 ASSERT_TRUE(response->headers);
3958 EXPECT_TRUE(response->headers->IsKeepAlive());
3959 EXPECT_EQ(200, response->headers->response_code());
3960 std::string body;
bnc691fda62016-08-12 00:43:163961 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543962 EXPECT_EQ("hello", body);
3963}
3964
[email protected]a8e9b162009-03-12 00:06:443965// Test that we don't read the response body when we fail to establish a tunnel,
3966// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013967TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273968 HttpRequestInfo request;
3969 request.method = "GET";
bncce36dca22015-04-21 22:11:233970 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103971 request.traffic_annotation =
3972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273973
[email protected]a8e9b162009-03-12 00:06:443974 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:563975 session_deps_.proxy_resolution_service =
3976 ConfiguredProxyResolutionService::CreateFixed(
3977 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443978
danakj1fd259a02016-04-16 03:17:093979 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443980
bnc691fda62016-08-12 00:43:163981 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443982
[email protected]a8e9b162009-03-12 00:06:443983 // Since we have proxy, should try to establish tunnel.
3984 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173985 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3986 "Host: www.example.org:443\r\n"
3987 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443988 };
3989
3990 // The proxy responds to the connect with a 407.
3991 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243992 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3993 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3994 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233995 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243996 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443997 };
3998
Ryan Sleevib8d7ea02018-05-07 20:01:013999 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074000 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444001
[email protected]49639fa2011-12-20 23:22:414002 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444003
tfarina42834112016-09-22 13:38:204004 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014005 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444006
4007 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014008 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444009
bnc691fda62016-08-12 00:43:164010 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244011 ASSERT_TRUE(response);
4012 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444013 EXPECT_TRUE(response->headers->IsKeepAlive());
4014 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424015 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444016
4017 std::string response_data;
bnc691fda62016-08-12 00:43:164018 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014019 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184020
4021 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114022 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]a8e9b162009-03-12 00:06:444023}
4024
Matt Menke96092e62019-10-18 04:09:334025// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4026// are the same, but the user/passwords are different. Serves to verify
4027// credentials are correctly separated based on HttpAuth::Target.
4028TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
4029 HttpRequestInfo request;
4030 request.method = "GET";
4031 request.url = GURL("http://myproxy:70/");
4032 request.traffic_annotation =
4033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4034
4035 // Proxy matches request URL.
4036 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564037 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke96092e62019-10-18 04:09:334038 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144039 RecordingBoundTestNetLog log;
Matt Menke96092e62019-10-18 04:09:334040 session_deps_.net_log = log.bound().net_log();
4041 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4042
4043 MockWrite data_writes[] = {
4044 // Initial request gets a proxy auth challenge.
4045 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4046 "Host: myproxy:70\r\n"
4047 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264048 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334049 // challenge.
4050 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4051 "Host: myproxy:70\r\n"
4052 "Proxy-Connection: keep-alive\r\n"
4053 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264054 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334055 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4056 "Host: myproxy:70\r\n"
4057 "Proxy-Connection: keep-alive\r\n"
4058 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4059 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4060 // A second request should preemptively send the correct proxy and server
4061 // auth headers.
4062 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4063 "Host: myproxy:70\r\n"
4064 "Proxy-Connection: keep-alive\r\n"
4065 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4066 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4067 };
4068
4069 MockRead data_reads[] = {
4070 // Proxy auth challenge.
4071 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4072 "Proxy-Connection: keep-alive\r\n"
4073 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4074 "Content-Length: 0\r\n\r\n"),
4075 // Server auth challenge.
4076 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4077 "Proxy-Connection: keep-alive\r\n"
4078 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4079 "Content-Length: 0\r\n\r\n"),
4080 // Response.
4081 MockRead("HTTP/1.1 200 OK\r\n"
4082 "Proxy-Connection: keep-alive\r\n"
4083 "Content-Length: 5\r\n\r\n"
4084 "hello"),
4085 // Response to second request.
4086 MockRead("HTTP/1.1 200 OK\r\n"
4087 "Proxy-Connection: keep-alive\r\n"
4088 "Content-Length: 2\r\n\r\n"
4089 "hi"),
4090 };
4091
4092 StaticSocketDataProvider data(data_reads, data_writes);
4093 session_deps_.socket_factory->AddSocketDataProvider(&data);
4094
4095 TestCompletionCallback callback;
4096
4097 auto trans =
4098 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4099 int rv = trans->Start(&request, callback.callback(), log.bound());
4100 EXPECT_THAT(callback.GetResult(rv), IsOk());
4101 const HttpResponseInfo* response = trans->GetResponseInfo();
4102 ASSERT_TRUE(response);
4103 ASSERT_TRUE(response->headers);
4104 EXPECT_EQ(407, response->headers->response_code());
4105 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4106
4107 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4108 EXPECT_THAT(callback.GetResult(rv), IsOk());
4109 response = trans->GetResponseInfo();
4110 ASSERT_TRUE(response);
4111 EXPECT_EQ(401, response->headers->response_code());
4112 EXPECT_FALSE(response->auth_challenge->is_proxy);
4113 EXPECT_EQ("http://myproxy:70",
4114 response->auth_challenge->challenger.Serialize());
4115 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4116 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4117
4118 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4119 callback.callback());
4120 EXPECT_THAT(callback.GetResult(rv), IsOk());
4121 response = trans->GetResponseInfo();
4122 ASSERT_TRUE(response);
4123 EXPECT_EQ(200, response->headers->response_code());
4124 // The password prompt info should not be set.
4125 EXPECT_FALSE(response->auth_challenge.has_value());
4126
4127 std::string response_data;
4128 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4129 EXPECT_EQ("hello", response_data);
4130
4131 // Check that the credentials were cached correctly.
4132 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4133 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264134 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334135 ASSERT_TRUE(entry);
4136 ASSERT_EQ(kFoo, entry->credentials().username());
4137 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264138 entry = session->http_auth_cache()->Lookup(
4139 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4140 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334141 ASSERT_TRUE(entry);
4142 ASSERT_EQ(kFoo2, entry->credentials().username());
4143 ASSERT_EQ(kBar2, entry->credentials().password());
4144
4145 // Make another request, which should automatically send the correct proxy and
4146 // server auth credentials and get another response.
4147 trans =
4148 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4149 rv = trans->Start(&request, callback.callback(), log.bound());
4150 EXPECT_THAT(callback.GetResult(rv), IsOk());
4151 response = trans->GetResponseInfo();
4152 ASSERT_TRUE(response);
4153 EXPECT_EQ(200, response->headers->response_code());
4154 // The password prompt info should not be set.
4155 EXPECT_FALSE(response->auth_challenge.has_value());
4156
4157 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4158 EXPECT_EQ("hi", response_data);
4159
4160 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114161 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menke96092e62019-10-18 04:09:334162}
4163
Matt Menkebe090422019-10-18 20:25:264164// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4165// are the same, but the user/passwords are different, and with different
4166// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4167// and auth challenges, sends another request with another NIK, expecting only
4168// the proxy credentials to be cached, and thus sees only a server auth
4169// challenge. Then sends a request with the original NIK, expecting cached proxy
4170// and auth credentials that match the ones used in the first request.
4171//
4172// Serves to verify credentials are correctly separated based on
4173// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4174// affects server credentials, not proxy credentials.
4175TEST_F(HttpNetworkTransactionTest,
4176 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
4177 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4178 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4179 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4180 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4181
4182 // This test would need to use a single socket without this option enabled.
4183 // Best to use this option when it would affect a test, as it will eventually
4184 // become the default behavior.
4185 base::test::ScopedFeatureList feature_list;
4186 feature_list.InitAndEnableFeature(
4187 features::kPartitionConnectionsByNetworkIsolationKey);
4188
4189 // Proxy matches request URL.
4190 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564191 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264192 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144193 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264194 session_deps_.net_log = log.bound().net_log();
4195 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4196 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4197
4198 MockWrite data_writes[] = {
4199 // Initial request gets a proxy auth challenge.
4200 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4201 "Host: myproxy:70\r\n"
4202 "Proxy-Connection: keep-alive\r\n\r\n"),
4203 // Retry with proxy auth credentials, which will result in a server auth
4204 // challenge.
4205 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4206 "Host: myproxy:70\r\n"
4207 "Proxy-Connection: keep-alive\r\n"
4208 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4209 // Retry with proxy and server auth credentials, which gets a response.
4210 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4211 "Host: myproxy:70\r\n"
4212 "Proxy-Connection: keep-alive\r\n"
4213 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4214 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4215 // Another request to the same server and using the same NIK should
4216 // preemptively send the correct cached proxy and server
4217 // auth headers.
4218 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4219 "Host: myproxy:70\r\n"
4220 "Proxy-Connection: keep-alive\r\n"
4221 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4222 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4223 };
4224
4225 MockRead data_reads[] = {
4226 // Proxy auth challenge.
4227 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4228 "Proxy-Connection: keep-alive\r\n"
4229 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4230 "Content-Length: 0\r\n\r\n"),
4231 // Server auth challenge.
4232 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4233 "Proxy-Connection: keep-alive\r\n"
4234 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4235 "Content-Length: 0\r\n\r\n"),
4236 // Response.
4237 MockRead("HTTP/1.1 200 OK\r\n"
4238 "Proxy-Connection: keep-alive\r\n"
4239 "Content-Length: 5\r\n\r\n"
4240 "hello"),
4241 // Response to second request.
4242 MockRead("HTTP/1.1 200 OK\r\n"
4243 "Proxy-Connection: keep-alive\r\n"
4244 "Content-Length: 2\r\n\r\n"
4245 "hi"),
4246 };
4247
4248 StaticSocketDataProvider data(data_reads, data_writes);
4249 session_deps_.socket_factory->AddSocketDataProvider(&data);
4250
4251 MockWrite data_writes2[] = {
4252 // Initial request using a different NetworkIsolationKey includes the
4253 // cached proxy credentials, but not server credentials.
4254 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4255 "Host: myproxy:70\r\n"
4256 "Proxy-Connection: keep-alive\r\n"
4257 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4258 // Retry with proxy and new server auth credentials, which gets a
4259 // response.
4260 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4261 "Host: myproxy:70\r\n"
4262 "Proxy-Connection: keep-alive\r\n"
4263 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4264 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4265 };
4266
4267 MockRead data_reads2[] = {
4268 // Server auth challenge.
4269 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4270 "Proxy-Connection: keep-alive\r\n"
4271 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4272 "Content-Length: 0\r\n\r\n"),
4273 // Response.
4274 MockRead("HTTP/1.1 200 OK\r\n"
4275 "Proxy-Connection: keep-alive\r\n"
4276 "Content-Length: 9\r\n\r\n"
4277 "greetings"),
4278 };
4279
4280 StaticSocketDataProvider data2(data_reads2, data_writes2);
4281 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4282
4283 TestCompletionCallback callback;
4284
4285 HttpRequestInfo request;
4286 request.method = "GET";
4287 request.url = GURL("http://myproxy:70/");
4288 request.traffic_annotation =
4289 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4290 request.network_isolation_key = kNetworkIsolationKey1;
4291
4292 auto trans =
4293 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4294 int rv = trans->Start(&request, callback.callback(), log.bound());
4295 EXPECT_THAT(callback.GetResult(rv), IsOk());
4296 const HttpResponseInfo* response = trans->GetResponseInfo();
4297 ASSERT_TRUE(response);
4298 ASSERT_TRUE(response->headers);
4299 EXPECT_EQ(407, response->headers->response_code());
4300 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4301
4302 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4303 EXPECT_THAT(callback.GetResult(rv), IsOk());
4304 response = trans->GetResponseInfo();
4305 ASSERT_TRUE(response);
4306 EXPECT_EQ(401, response->headers->response_code());
4307 EXPECT_FALSE(response->auth_challenge->is_proxy);
4308 EXPECT_EQ("http://myproxy:70",
4309 response->auth_challenge->challenger.Serialize());
4310 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4311 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4312
4313 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4314 callback.callback());
4315 EXPECT_THAT(callback.GetResult(rv), IsOk());
4316 response = trans->GetResponseInfo();
4317 ASSERT_TRUE(response);
4318 EXPECT_EQ(200, response->headers->response_code());
4319 // The password prompt info should not be set.
4320 EXPECT_FALSE(response->auth_challenge.has_value());
4321 std::string response_data;
4322 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4323 EXPECT_EQ("hello", response_data);
4324
4325 // Check that the proxy credentials were cached correctly. The should be
4326 // accessible with any NetworkIsolationKey.
4327 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4328 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4329 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4330 ASSERT_TRUE(entry);
4331 ASSERT_EQ(kFoo, entry->credentials().username());
4332 ASSERT_EQ(kBar, entry->credentials().password());
4333 EXPECT_EQ(entry,
4334 session->http_auth_cache()->Lookup(
4335 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4336 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4337
4338 // Check that the server credentials were cached correctly. The should be
4339 // accessible with only kNetworkIsolationKey1.
4340 entry = session->http_auth_cache()->Lookup(
4341 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4342 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4343 ASSERT_TRUE(entry);
4344 ASSERT_EQ(kFoo2, entry->credentials().username());
4345 ASSERT_EQ(kBar2, entry->credentials().password());
4346 // Looking up the server entry with another NetworkIsolationKey should fail.
4347 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4348 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4349 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4350
4351 // Make another request with a different NetworkIsolationKey. It should use
4352 // another socket, reuse the cached proxy credentials, but result in a server
4353 // auth challenge.
4354 request.network_isolation_key = kNetworkIsolationKey2;
4355 trans =
4356 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4357 rv = trans->Start(&request, callback.callback(), log.bound());
4358 EXPECT_THAT(callback.GetResult(rv), IsOk());
4359 response = trans->GetResponseInfo();
4360 ASSERT_TRUE(response);
4361 EXPECT_EQ(401, response->headers->response_code());
4362 EXPECT_FALSE(response->auth_challenge->is_proxy);
4363 EXPECT_EQ("http://myproxy:70",
4364 response->auth_challenge->challenger.Serialize());
4365 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4366 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4367
4368 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4369 callback.callback());
4370 EXPECT_THAT(callback.GetResult(rv), IsOk());
4371 response = trans->GetResponseInfo();
4372 ASSERT_TRUE(response);
4373 EXPECT_EQ(200, response->headers->response_code());
4374 // The password prompt info should not be set.
4375 EXPECT_FALSE(response->auth_challenge.has_value());
4376 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4377 EXPECT_EQ("greetings", response_data);
4378
4379 // Check that the proxy credentials are still cached.
4380 entry = session->http_auth_cache()->Lookup(
4381 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4382 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4383 ASSERT_TRUE(entry);
4384 ASSERT_EQ(kFoo, entry->credentials().username());
4385 ASSERT_EQ(kBar, entry->credentials().password());
4386 EXPECT_EQ(entry,
4387 session->http_auth_cache()->Lookup(
4388 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4389 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4390
4391 // Check that the correct server credentials are cached for each
4392 // NetworkIsolationKey.
4393 entry = session->http_auth_cache()->Lookup(
4394 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4395 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4396 ASSERT_TRUE(entry);
4397 ASSERT_EQ(kFoo2, entry->credentials().username());
4398 ASSERT_EQ(kBar2, entry->credentials().password());
4399 entry = session->http_auth_cache()->Lookup(
4400 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4401 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4402 ASSERT_TRUE(entry);
4403 ASSERT_EQ(kFoo3, entry->credentials().username());
4404 ASSERT_EQ(kBar3, entry->credentials().password());
4405
4406 // Make a request with the original NetworkIsolationKey. It should reuse the
4407 // first socket, and the proxy credentials sent on the first socket.
4408 request.network_isolation_key = kNetworkIsolationKey1;
4409 trans =
4410 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4411 rv = trans->Start(&request, callback.callback(), log.bound());
4412 EXPECT_THAT(callback.GetResult(rv), IsOk());
4413 response = trans->GetResponseInfo();
4414 ASSERT_TRUE(response);
4415 EXPECT_EQ(200, response->headers->response_code());
4416 // The password prompt info should not be set.
4417 EXPECT_FALSE(response->auth_challenge.has_value());
4418 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4419 EXPECT_EQ("hi", response_data);
4420
4421 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114422 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264423}
4424
4425// Much like the test above, but uses tunnelled connections.
4426TEST_F(HttpNetworkTransactionTest,
4427 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
4428 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4429 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4430 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4431 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4432
4433 // This test would need to use a single socket without this option enabled.
4434 // Best to use this option when it would affect a test, as it will eventually
4435 // become the default behavior.
4436 base::test::ScopedFeatureList feature_list;
4437 feature_list.InitAndEnableFeature(
4438 features::kPartitionConnectionsByNetworkIsolationKey);
4439
4440 // Proxy matches request URL.
4441 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564442 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264443 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144444 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264445 session_deps_.net_log = log.bound().net_log();
4446 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4447 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4448
4449 MockWrite data_writes[] = {
4450 // Initial tunnel request gets a proxy auth challenge.
4451 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4452 "Host: myproxy:70\r\n"
4453 "Proxy-Connection: keep-alive\r\n\r\n"),
4454 // Retry with proxy auth credentials, which will result in establishing a
4455 // tunnel.
4456 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4457 "Host: myproxy:70\r\n"
4458 "Proxy-Connection: keep-alive\r\n"
4459 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4460 // Request over the tunnel, which gets a server auth challenge.
4461 MockWrite("GET / HTTP/1.1\r\n"
4462 "Host: myproxy:70\r\n"
4463 "Connection: keep-alive\r\n\r\n"),
4464 // Retry with server auth credentials, which gets a response.
4465 MockWrite("GET / HTTP/1.1\r\n"
4466 "Host: myproxy:70\r\n"
4467 "Connection: keep-alive\r\n"
4468 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4469 // Another request to the same server and using the same NIK should
4470 // preemptively send the correct cached server
4471 // auth header. Since a tunnel was already established, the proxy headers
4472 // won't be sent again except when establishing another tunnel.
4473 MockWrite("GET / HTTP/1.1\r\n"
4474 "Host: myproxy:70\r\n"
4475 "Connection: keep-alive\r\n"
4476 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4477 };
4478
4479 MockRead data_reads[] = {
4480 // Proxy auth challenge.
4481 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4482 "Proxy-Connection: keep-alive\r\n"
4483 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4484 "Content-Length: 0\r\n\r\n"),
4485 // Tunnel success
4486 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4487 // Server auth challenge.
4488 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4489 "Connection: keep-alive\r\n"
4490 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4491 "Content-Length: 0\r\n\r\n"),
4492 // Response.
4493 MockRead("HTTP/1.1 200 OK\r\n"
4494 "Connection: keep-alive\r\n"
4495 "Content-Length: 5\r\n\r\n"
4496 "hello"),
4497 // Response to second request.
4498 MockRead("HTTP/1.1 200 OK\r\n"
4499 "Connection: keep-alive\r\n"
4500 "Content-Length: 2\r\n\r\n"
4501 "hi"),
4502 };
4503
4504 StaticSocketDataProvider data(data_reads, data_writes);
4505 session_deps_.socket_factory->AddSocketDataProvider(&data);
4506 // One for the proxy connection, one of the server connection.
4507 SSLSocketDataProvider ssl(ASYNC, OK);
4508 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4509 SSLSocketDataProvider ssl2(ASYNC, OK);
4510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4511
4512 MockWrite data_writes2[] = {
4513 // Initial request using a different NetworkIsolationKey includes the
4514 // cached proxy credentials when establishing a tunnel.
4515 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4516 "Host: myproxy:70\r\n"
4517 "Proxy-Connection: keep-alive\r\n"
4518 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4519 // Request over the tunnel, which gets a server auth challenge. Cached
4520 // credentials cannot be used, since the NIK is different.
4521 MockWrite("GET / HTTP/1.1\r\n"
4522 "Host: myproxy:70\r\n"
4523 "Connection: keep-alive\r\n\r\n"),
4524 // Retry with server auth credentials, which gets a response.
4525 MockWrite("GET / HTTP/1.1\r\n"
4526 "Host: myproxy:70\r\n"
4527 "Connection: keep-alive\r\n"
4528 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4529 };
4530
4531 MockRead data_reads2[] = {
4532 // Tunnel success
4533 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4534 // Server auth challenge.
4535 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4536 "Connection: keep-alive\r\n"
4537 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4538 "Content-Length: 0\r\n\r\n"),
4539 // Response.
4540 MockRead("HTTP/1.1 200 OK\r\n"
4541 "Connection: keep-alive\r\n"
4542 "Content-Length: 9\r\n\r\n"
4543 "greetings"),
4544 };
4545
4546 StaticSocketDataProvider data2(data_reads2, data_writes2);
4547 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4548 // One for the proxy connection, one of the server connection.
4549 SSLSocketDataProvider ssl3(ASYNC, OK);
4550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4551 SSLSocketDataProvider ssl4(ASYNC, OK);
4552 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4553
4554 TestCompletionCallback callback;
4555
4556 HttpRequestInfo request;
4557 request.method = "GET";
4558 request.url = GURL("https://myproxy:70/");
4559 request.traffic_annotation =
4560 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4561 request.network_isolation_key = kNetworkIsolationKey1;
4562
4563 auto trans =
4564 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4565 int rv = trans->Start(&request, callback.callback(), log.bound());
4566 EXPECT_THAT(callback.GetResult(rv), IsOk());
4567 const HttpResponseInfo* response = trans->GetResponseInfo();
4568 ASSERT_TRUE(response);
4569 ASSERT_TRUE(response->headers);
4570 EXPECT_EQ(407, response->headers->response_code());
4571 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4572
4573 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4574 EXPECT_THAT(callback.GetResult(rv), IsOk());
4575 response = trans->GetResponseInfo();
4576 ASSERT_TRUE(response);
4577 EXPECT_EQ(401, response->headers->response_code());
4578 EXPECT_FALSE(response->auth_challenge->is_proxy);
4579 EXPECT_EQ("https://myproxy:70",
4580 response->auth_challenge->challenger.Serialize());
4581 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4582 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4583
4584 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4585 callback.callback());
4586 EXPECT_THAT(callback.GetResult(rv), IsOk());
4587 response = trans->GetResponseInfo();
4588 ASSERT_TRUE(response);
4589 EXPECT_EQ(200, response->headers->response_code());
4590 // The password prompt info should not be set.
4591 EXPECT_FALSE(response->auth_challenge.has_value());
4592 std::string response_data;
4593 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4594 EXPECT_EQ("hello", response_data);
4595
4596 // Check that the proxy credentials were cached correctly. The should be
4597 // accessible with any NetworkIsolationKey.
4598 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4599 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4600 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4601 ASSERT_TRUE(entry);
4602 ASSERT_EQ(kFoo, entry->credentials().username());
4603 ASSERT_EQ(kBar, entry->credentials().password());
4604 EXPECT_EQ(entry,
4605 session->http_auth_cache()->Lookup(
4606 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4607 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4608
4609 // Check that the server credentials were cached correctly. The should be
4610 // accessible with only kNetworkIsolationKey1.
4611 entry = session->http_auth_cache()->Lookup(
4612 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4613 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4614 ASSERT_TRUE(entry);
4615 ASSERT_EQ(kFoo2, entry->credentials().username());
4616 ASSERT_EQ(kBar2, entry->credentials().password());
4617 // Looking up the server entry with another NetworkIsolationKey should fail.
4618 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4619 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4620 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4621
4622 // Make another request with a different NetworkIsolationKey. It should use
4623 // another socket, reuse the cached proxy credentials, but result in a server
4624 // auth challenge.
4625 request.network_isolation_key = kNetworkIsolationKey2;
4626 trans =
4627 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4628 rv = trans->Start(&request, callback.callback(), log.bound());
4629 EXPECT_THAT(callback.GetResult(rv), IsOk());
4630 response = trans->GetResponseInfo();
4631 ASSERT_TRUE(response);
4632 EXPECT_EQ(401, response->headers->response_code());
4633 EXPECT_FALSE(response->auth_challenge->is_proxy);
4634 EXPECT_EQ("https://myproxy:70",
4635 response->auth_challenge->challenger.Serialize());
4636 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4637 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4638
4639 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4640 callback.callback());
4641 EXPECT_THAT(callback.GetResult(rv), IsOk());
4642 response = trans->GetResponseInfo();
4643 ASSERT_TRUE(response);
4644 EXPECT_EQ(200, response->headers->response_code());
4645 // The password prompt info should not be set.
4646 EXPECT_FALSE(response->auth_challenge.has_value());
4647 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4648 EXPECT_EQ("greetings", response_data);
4649
4650 // Check that the proxy credentials are still cached.
4651 entry = session->http_auth_cache()->Lookup(
4652 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4653 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4654 ASSERT_TRUE(entry);
4655 ASSERT_EQ(kFoo, entry->credentials().username());
4656 ASSERT_EQ(kBar, entry->credentials().password());
4657 EXPECT_EQ(entry,
4658 session->http_auth_cache()->Lookup(
4659 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4660 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4661
4662 // Check that the correct server credentials are cached for each
4663 // NetworkIsolationKey.
4664 entry = session->http_auth_cache()->Lookup(
4665 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4666 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4667 ASSERT_TRUE(entry);
4668 ASSERT_EQ(kFoo2, entry->credentials().username());
4669 ASSERT_EQ(kBar2, entry->credentials().password());
4670 entry = session->http_auth_cache()->Lookup(
4671 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4672 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4673 ASSERT_TRUE(entry);
4674 ASSERT_EQ(kFoo3, entry->credentials().username());
4675 ASSERT_EQ(kBar3, entry->credentials().password());
4676
4677 // Make a request with the original NetworkIsolationKey. It should reuse the
4678 // first socket, and the proxy credentials sent on the first socket.
4679 request.network_isolation_key = kNetworkIsolationKey1;
4680 trans =
4681 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4682 rv = trans->Start(&request, callback.callback(), log.bound());
4683 EXPECT_THAT(callback.GetResult(rv), IsOk());
4684 response = trans->GetResponseInfo();
4685 ASSERT_TRUE(response);
4686 EXPECT_EQ(200, response->headers->response_code());
4687 // The password prompt info should not be set.
4688 EXPECT_FALSE(response->auth_challenge.has_value());
4689 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4690 EXPECT_EQ("hi", response_data);
4691
4692 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114693 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264694}
4695
ttuttle7933c112015-01-06 00:55:244696// Test that we don't pass extraneous headers from the proxy's response to the
4697// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014698TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244699 HttpRequestInfo request;
4700 request.method = "GET";
bncce36dca22015-04-21 22:11:234701 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104702 request.traffic_annotation =
4703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244704
4705 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564706 session_deps_.proxy_resolution_service =
4707 ConfiguredProxyResolutionService::CreateFixed(
4708 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244709
danakj1fd259a02016-04-16 03:17:094710 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244711
bnc691fda62016-08-12 00:43:164712 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244713
4714 // Since we have proxy, should try to establish tunnel.
4715 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174716 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4717 "Host: www.example.org:443\r\n"
4718 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244719 };
4720
4721 // The proxy responds to the connect with a 407.
4722 MockRead data_reads[] = {
4723 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4724 MockRead("X-Foo: bar\r\n"),
4725 MockRead("Set-Cookie: foo=bar\r\n"),
4726 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4727 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234728 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244729 };
4730
Ryan Sleevib8d7ea02018-05-07 20:01:014731 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244732 session_deps_.socket_factory->AddSocketDataProvider(&data);
4733
4734 TestCompletionCallback callback;
4735
tfarina42834112016-09-22 13:38:204736 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014737 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244738
4739 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014740 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244741
bnc691fda62016-08-12 00:43:164742 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244743 ASSERT_TRUE(response);
4744 ASSERT_TRUE(response->headers);
4745 EXPECT_TRUE(response->headers->IsKeepAlive());
4746 EXPECT_EQ(407, response->headers->response_code());
4747 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4748 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4749 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4750
4751 std::string response_data;
bnc691fda62016-08-12 00:43:164752 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014753 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244754
4755 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114756 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle7933c112015-01-06 00:55:244757}
4758
[email protected]8fdbcd22010-05-05 02:54:524759// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4760// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014761TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524762 HttpRequestInfo request;
4763 request.method = "GET";
bncce36dca22015-04-21 22:11:234764 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104765 request.traffic_annotation =
4766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524767
[email protected]cb9bf6ca2011-01-28 13:15:274768 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164770 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274771
[email protected]8fdbcd22010-05-05 02:54:524772 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234773 MockWrite(
4774 "GET / HTTP/1.1\r\n"
4775 "Host: www.example.org\r\n"
4776 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524777 };
4778
4779 MockRead data_reads1[] = {
4780 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4781 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4782 // Large content-length -- won't matter, as connection will be reset.
4783 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064784 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524785 };
4786
Ryan Sleevib8d7ea02018-05-07 20:01:014787 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074788 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524789
[email protected]49639fa2011-12-20 23:22:414790 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524791
tfarina42834112016-09-22 13:38:204792 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524794
4795 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014796 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524797}
4798
[email protected]7a67a8152010-11-05 18:31:104799// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4800// through a non-authenticating proxy. The request should fail with
4801// ERR_UNEXPECTED_PROXY_AUTH.
4802// Note that it is impossible to detect if an HTTP server returns a 407 through
4803// a non-authenticating proxy - there is nothing to indicate whether the
4804// response came from the proxy or the server, so it is treated as if the proxy
4805// issued the challenge.
bncd16676a2016-07-20 16:23:014806TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274807 HttpRequestInfo request;
4808 request.method = "GET";
bncce36dca22015-04-21 22:11:234809 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104810 request.traffic_annotation =
4811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274812
Nicolas Arciniegad2013f92020-02-07 23:00:564813 session_deps_.proxy_resolution_service =
4814 ConfiguredProxyResolutionService::CreateFixed(
4815 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144816 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074817 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094818 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104819
[email protected]7a67a8152010-11-05 18:31:104820 // Since we have proxy, should try to establish tunnel.
4821 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174822 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4823 "Host: www.example.org:443\r\n"
4824 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104825
rsleevidb16bb02015-11-12 23:47:174826 MockWrite("GET / HTTP/1.1\r\n"
4827 "Host: www.example.org\r\n"
4828 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104829 };
4830
4831 MockRead data_reads1[] = {
4832 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4833
4834 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4835 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4836 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064837 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104838 };
4839
Ryan Sleevib8d7ea02018-05-07 20:01:014840 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074841 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064842 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104844
[email protected]49639fa2011-12-20 23:22:414845 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104846
bnc691fda62016-08-12 00:43:164847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104848
bnc691fda62016-08-12 00:43:164849 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014850 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104851
4852 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014853 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544854 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104855 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004856 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4857 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104858 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404859 entries, pos,
mikecirone8b85c432016-09-08 19:11:004860 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4861 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104862}
[email protected]2df19bb2010-08-25 20:13:464863
mmenke2a1781d2015-10-07 19:25:334864// Test a proxy auth scheme that allows default credentials and a proxy server
4865// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014866TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334867 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4868 HttpRequestInfo request;
4869 request.method = "GET";
4870 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104871 request.traffic_annotation =
4872 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334873
4874 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594875 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564876 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:494877 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334878
Jeremy Roman0579ed62017-08-29 15:56:194879 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334880 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194881 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334882 mock_handler->set_allows_default_credentials(true);
4883 auth_handler_factory->AddMockHandler(mock_handler.release(),
4884 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484885 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334886
4887 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:584888 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:094889 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334890
4891 // Since we have proxy, should try to establish tunnel.
4892 MockWrite data_writes1[] = {
4893 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174894 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334895 "Proxy-Connection: keep-alive\r\n\r\n"),
4896 };
4897
4898 // The proxy responds to the connect with a 407, using a non-persistent
4899 // connection.
4900 MockRead data_reads1[] = {
4901 // No credentials.
4902 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4903 MockRead("Proxy-Authenticate: Mock\r\n"),
4904 MockRead("Proxy-Connection: close\r\n\r\n"),
4905 };
4906
4907 // Since the first connection couldn't be reused, need to establish another
4908 // once given credentials.
4909 MockWrite data_writes2[] = {
4910 // After calling trans->RestartWithAuth(), this is the request we should
4911 // be issuing -- the final header line contains the credentials.
4912 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174913 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334914 "Proxy-Connection: keep-alive\r\n"
4915 "Proxy-Authorization: auth_token\r\n\r\n"),
4916
4917 MockWrite("GET / HTTP/1.1\r\n"
4918 "Host: www.example.org\r\n"
4919 "Connection: keep-alive\r\n\r\n"),
4920 };
4921
4922 MockRead data_reads2[] = {
4923 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4924
4925 MockRead("HTTP/1.1 200 OK\r\n"),
4926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4927 MockRead("Content-Length: 5\r\n\r\n"),
4928 MockRead(SYNCHRONOUS, "hello"),
4929 };
4930
Ryan Sleevib8d7ea02018-05-07 20:01:014931 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334932 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014933 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334934 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4935 SSLSocketDataProvider ssl(ASYNC, OK);
4936 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4937
bnc87dcefc2017-05-25 12:47:584938 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194939 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334940
4941 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204942 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014943 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334944
4945 const HttpResponseInfo* response = trans->GetResponseInfo();
4946 ASSERT_TRUE(response);
4947 ASSERT_TRUE(response->headers);
4948 EXPECT_FALSE(response->headers->IsKeepAlive());
4949 EXPECT_EQ(407, response->headers->response_code());
4950 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4951 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584952 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334953
4954 LoadTimingInfo load_timing_info;
4955 // CONNECT requests and responses are handled at the connect job level, so
4956 // the transaction does not yet have a connection.
4957 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4958
4959 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014960 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334961 response = trans->GetResponseInfo();
4962 ASSERT_TRUE(response);
4963 ASSERT_TRUE(response->headers);
4964 EXPECT_TRUE(response->headers->IsKeepAlive());
4965 EXPECT_EQ(200, response->headers->response_code());
4966 EXPECT_EQ(5, response->headers->GetContentLength());
4967 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4968
4969 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584970 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334971
4972 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4973 TestLoadTimingNotReusedWithPac(load_timing_info,
4974 CONNECT_TIMING_HAS_SSL_TIMES);
4975
4976 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114977 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:334978}
4979
4980// Test a proxy auth scheme that allows default credentials and a proxy server
4981// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014982TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334983 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4984 HttpRequestInfo request;
4985 request.method = "GET";
4986 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104987 request.traffic_annotation =
4988 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334989
4990 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594991 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564992 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:494993 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334994
Jeremy Roman0579ed62017-08-29 15:56:194995 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334996 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194997 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334998 mock_handler->set_allows_default_credentials(true);
4999 auth_handler_factory->AddMockHandler(mock_handler.release(),
5000 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485001 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335002
5003 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585004 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095005 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335006
5007 // Should try to establish tunnel.
5008 MockWrite data_writes1[] = {
5009 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175010 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335011 "Proxy-Connection: keep-alive\r\n\r\n"),
5012
5013 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175014 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335015 "Proxy-Connection: keep-alive\r\n"
5016 "Proxy-Authorization: auth_token\r\n\r\n"),
5017 };
5018
5019 // The proxy responds to the connect with a 407, using a non-persistent
5020 // connection.
5021 MockRead data_reads1[] = {
5022 // No credentials.
5023 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5024 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5025 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5026 };
5027
5028 // Since the first connection was closed, need to establish another once given
5029 // credentials.
5030 MockWrite data_writes2[] = {
5031 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175032 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335033 "Proxy-Connection: keep-alive\r\n"
5034 "Proxy-Authorization: auth_token\r\n\r\n"),
5035
5036 MockWrite("GET / HTTP/1.1\r\n"
5037 "Host: www.example.org\r\n"
5038 "Connection: keep-alive\r\n\r\n"),
5039 };
5040
5041 MockRead data_reads2[] = {
5042 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5043
5044 MockRead("HTTP/1.1 200 OK\r\n"),
5045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5046 MockRead("Content-Length: 5\r\n\r\n"),
5047 MockRead(SYNCHRONOUS, "hello"),
5048 };
5049
Ryan Sleevib8d7ea02018-05-07 20:01:015050 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335051 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015052 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335053 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5054 SSLSocketDataProvider ssl(ASYNC, OK);
5055 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5056
bnc87dcefc2017-05-25 12:47:585057 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195058 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335059
5060 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205061 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015062 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335063
5064 const HttpResponseInfo* response = trans->GetResponseInfo();
5065 ASSERT_TRUE(response);
5066 ASSERT_TRUE(response->headers);
5067 EXPECT_TRUE(response->headers->IsKeepAlive());
5068 EXPECT_EQ(407, response->headers->response_code());
5069 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5070 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585071 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335072
5073 LoadTimingInfo load_timing_info;
5074 // CONNECT requests and responses are handled at the connect job level, so
5075 // the transaction does not yet have a connection.
5076 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5077
5078 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015079 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335080
5081 response = trans->GetResponseInfo();
5082 ASSERT_TRUE(response);
5083 ASSERT_TRUE(response->headers);
5084 EXPECT_TRUE(response->headers->IsKeepAlive());
5085 EXPECT_EQ(200, response->headers->response_code());
5086 EXPECT_EQ(5, response->headers->GetContentLength());
5087 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5088
5089 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585090 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335091
5092 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5093 TestLoadTimingNotReusedWithPac(load_timing_info,
5094 CONNECT_TIMING_HAS_SSL_TIMES);
5095
5096 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115097 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335098}
5099
5100// Test a proxy auth scheme that allows default credentials and a proxy server
5101// that hangs up when credentials are initially sent, and hangs up again when
5102// they are retried.
bncd16676a2016-07-20 16:23:015103TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335104 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5105 HttpRequestInfo request;
5106 request.method = "GET";
5107 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105108 request.traffic_annotation =
5109 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335110
5111 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595112 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565113 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495114 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335115
Jeremy Roman0579ed62017-08-29 15:56:195116 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335117 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195118 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335119 mock_handler->set_allows_default_credentials(true);
5120 auth_handler_factory->AddMockHandler(mock_handler.release(),
5121 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485122 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335123
5124 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585125 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095126 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335127
5128 // Should try to establish tunnel.
5129 MockWrite data_writes1[] = {
5130 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175131 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335132 "Proxy-Connection: keep-alive\r\n\r\n"),
5133
5134 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175135 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335136 "Proxy-Connection: keep-alive\r\n"
5137 "Proxy-Authorization: auth_token\r\n\r\n"),
5138 };
5139
5140 // The proxy responds to the connect with a 407, and then hangs up after the
5141 // second request is sent.
5142 MockRead data_reads1[] = {
5143 // No credentials.
5144 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5145 MockRead("Content-Length: 0\r\n"),
5146 MockRead("Proxy-Connection: keep-alive\r\n"),
5147 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5148 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5149 };
5150
5151 // HttpNetworkTransaction sees a reused connection that was closed with
5152 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5153 // request.
5154 MockWrite data_writes2[] = {
5155 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175156 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335157 "Proxy-Connection: keep-alive\r\n\r\n"),
5158 };
5159
5160 // The proxy, having had more than enough of us, just hangs up.
5161 MockRead data_reads2[] = {
5162 // No credentials.
5163 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5164 };
5165
Ryan Sleevib8d7ea02018-05-07 20:01:015166 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335167 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015168 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335169 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5170
bnc87dcefc2017-05-25 12:47:585171 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195172 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335173
5174 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205175 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015176 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335177
5178 const HttpResponseInfo* response = trans->GetResponseInfo();
5179 ASSERT_TRUE(response);
5180 ASSERT_TRUE(response->headers);
5181 EXPECT_TRUE(response->headers->IsKeepAlive());
5182 EXPECT_EQ(407, response->headers->response_code());
5183 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5184 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585185 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335186
5187 LoadTimingInfo load_timing_info;
5188 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5189
5190 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015191 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335192
5193 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115194 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335195}
5196
Asanka Herathbc3f8f62018-11-16 23:08:305197// This test exercises an odd edge case where the proxy closes the connection
5198// after the authentication handshake is complete. Presumably this technique is
5199// used in lieu of returning a 403 or 5xx status code when the authentication
5200// succeeds, but the user is not authorized to connect to the destination
5201// server. There's no standard for what a proxy should do to indicate a blocked
5202// site.
5203TEST_F(HttpNetworkTransactionTest,
5204 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5205 HttpRequestInfo request;
5206 request.method = "GET";
5207 request.url = GURL("https://www.example.org/");
5208 request.traffic_annotation =
5209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5210
5211 // Configure against proxy server "myproxy:70".
5212 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565213 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Asanka Herathbc3f8f62018-11-16 23:08:305214 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5215
5216 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5217 auth_handler_factory->set_do_init_from_challenge(true);
5218
5219 // Create two mock AuthHandlers. This is because the transaction gets retried
5220 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5221 // was a real network error.
5222 //
5223 // The handlers support both default and explicit credentials. The retry
5224 // mentioned above should be able to reuse the default identity. Thus there
5225 // should never be a need to prompt for explicit credentials.
5226 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5227 mock_handler->set_allows_default_credentials(true);
5228 mock_handler->set_allows_explicit_credentials(true);
5229 mock_handler->set_connection_based(true);
5230 auth_handler_factory->AddMockHandler(mock_handler.release(),
5231 HttpAuth::AUTH_PROXY);
5232 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5233 mock_handler->set_allows_default_credentials(true);
5234 mock_handler->set_allows_explicit_credentials(true);
5235 mock_handler->set_connection_based(true);
5236 auth_handler_factory->AddMockHandler(mock_handler.release(),
5237 HttpAuth::AUTH_PROXY);
5238 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5239
Matt Muellerde5dadf2019-11-27 20:11:585240 session_deps_.net_log = NetLog::Get();
Asanka Herathbc3f8f62018-11-16 23:08:305241 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5242
5243 // Data for both sockets.
5244 //
5245 // Writes are for the tunnel establishment attempts and the
5246 // authentication handshake.
5247 MockWrite data_writes1[] = {
5248 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5249 "Host: www.example.org:443\r\n"
5250 "Proxy-Connection: keep-alive\r\n\r\n"),
5251
5252 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5253 "Host: www.example.org:443\r\n"
5254 "Proxy-Connection: keep-alive\r\n"
5255 "Proxy-Authorization: auth_token\r\n\r\n"),
5256
5257 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5258 "Host: www.example.org:443\r\n"
5259 "Proxy-Connection: keep-alive\r\n"
5260 "Proxy-Authorization: auth_token\r\n\r\n"),
5261 };
5262
5263 // The server side of the authentication handshake. Note that the response to
5264 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5265 MockRead data_reads1[] = {
5266 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5267 MockRead("Content-Length: 0\r\n"),
5268 MockRead("Proxy-Connection: keep-alive\r\n"),
5269 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5270
5271 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5272 MockRead("Content-Length: 0\r\n"),
5273 MockRead("Proxy-Connection: keep-alive\r\n"),
5274 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5275
5276 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5277 };
5278
5279 StaticSocketDataProvider data1(data_reads1, data_writes1);
5280 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5281
5282 // The second socket is for the reconnection attempt. Data is identical to the
5283 // first attempt.
5284 StaticSocketDataProvider data2(data_reads1, data_writes1);
5285 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5286
5287 auto trans =
5288 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5289
5290 TestCompletionCallback callback;
5291 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5292
5293 // Two rounds per handshake. After one retry, the error is propagated up the
5294 // stack.
5295 for (int i = 0; i < 4; ++i) {
5296 EXPECT_THAT(callback.GetResult(rv), IsOk());
5297
5298 const HttpResponseInfo* response = trans->GetResponseInfo();
5299 ASSERT_TRUE(response);
5300 ASSERT_TRUE(response->headers);
5301 EXPECT_EQ(407, response->headers->response_code());
5302 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5303
5304 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5305 }
5306
5307 // One shall be the number thou shalt retry, and the number of the retrying
5308 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5309 // that thou then proceed to one. Three is right out. Once the number one,
5310 // being the first number, be reached, then lobbest thou thy
5311 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5312 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5313
5314 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115315 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Asanka Herathbc3f8f62018-11-16 23:08:305316}
5317
mmenke2a1781d2015-10-07 19:25:335318// Test a proxy auth scheme that allows default credentials and a proxy server
5319// that hangs up when credentials are initially sent, and sends a challenge
5320// again they are retried.
bncd16676a2016-07-20 16:23:015321TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335322 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5323 HttpRequestInfo request;
5324 request.method = "GET";
5325 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105326 request.traffic_annotation =
5327 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335328
5329 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595330 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565331 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495332 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335333
Jeremy Roman0579ed62017-08-29 15:56:195334 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335335 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195336 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335337 mock_handler->set_allows_default_credentials(true);
5338 auth_handler_factory->AddMockHandler(mock_handler.release(),
5339 HttpAuth::AUTH_PROXY);
5340 // Add another handler for the second challenge. It supports default
5341 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195342 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335343 mock_handler->set_allows_default_credentials(true);
5344 auth_handler_factory->AddMockHandler(mock_handler.release(),
5345 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485346 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335347
5348 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585349 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095350 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335351
5352 // Should try to establish tunnel.
5353 MockWrite data_writes1[] = {
5354 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175355 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335356 "Proxy-Connection: keep-alive\r\n\r\n"),
5357 };
5358
5359 // The proxy responds to the connect with a 407, using a non-persistent
5360 // connection.
5361 MockRead data_reads1[] = {
5362 // No credentials.
5363 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5364 MockRead("Proxy-Authenticate: Mock\r\n"),
5365 MockRead("Proxy-Connection: close\r\n\r\n"),
5366 };
5367
5368 // Since the first connection was closed, need to establish another once given
5369 // credentials.
5370 MockWrite data_writes2[] = {
5371 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175372 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335373 "Proxy-Connection: keep-alive\r\n"
5374 "Proxy-Authorization: auth_token\r\n\r\n"),
5375 };
5376
5377 MockRead data_reads2[] = {
5378 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5379 MockRead("Proxy-Authenticate: Mock\r\n"),
5380 MockRead("Proxy-Connection: close\r\n\r\n"),
5381 };
5382
Ryan Sleevib8d7ea02018-05-07 20:01:015383 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335384 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015385 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335386 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5387 SSLSocketDataProvider ssl(ASYNC, OK);
5388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5389
bnc87dcefc2017-05-25 12:47:585390 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195391 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335392
5393 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205394 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015395 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335396
5397 const HttpResponseInfo* response = trans->GetResponseInfo();
5398 ASSERT_TRUE(response);
5399 ASSERT_TRUE(response->headers);
5400 EXPECT_EQ(407, response->headers->response_code());
5401 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5402 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585403 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335404
5405 LoadTimingInfo load_timing_info;
5406 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5407
5408 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015409 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335410 response = trans->GetResponseInfo();
5411 ASSERT_TRUE(response);
5412 ASSERT_TRUE(response->headers);
5413 EXPECT_EQ(407, response->headers->response_code());
5414 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585415 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335416
5417 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115418 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335419}
5420
asankae2257db2016-10-11 22:03:165421// A more nuanced test than GenerateAuthToken test which asserts that
5422// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5423// unnecessarily invalidated, and that if the server co-operates, the
5424// authentication handshake can continue with the same scheme but with a
5425// different identity.
5426TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5427 HttpRequestInfo request;
5428 request.method = "GET";
5429 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105430 request.traffic_annotation =
5431 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165432
Jeremy Roman0579ed62017-08-29 15:56:195433 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165434 auth_handler_factory->set_do_init_from_challenge(true);
5435
5436 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195437 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165438 mock_handler->set_allows_default_credentials(true);
5439 mock_handler->set_allows_explicit_credentials(true);
5440 mock_handler->set_connection_based(true);
5441 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5442 auth_handler_factory->AddMockHandler(mock_handler.release(),
5443 HttpAuth::AUTH_SERVER);
5444
5445 // Add another handler for the second challenge. It supports default
5446 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195447 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165448 mock_handler->set_allows_default_credentials(true);
5449 mock_handler->set_allows_explicit_credentials(true);
5450 mock_handler->set_connection_based(true);
5451 auth_handler_factory->AddMockHandler(mock_handler.release(),
5452 HttpAuth::AUTH_SERVER);
5453 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5454
5455 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5456
5457 MockWrite data_writes1[] = {
5458 MockWrite("GET / HTTP/1.1\r\n"
5459 "Host: www.example.org\r\n"
5460 "Connection: keep-alive\r\n\r\n"),
5461 };
5462
5463 MockRead data_reads1[] = {
5464 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5465 "WWW-Authenticate: Mock\r\n"
5466 "Connection: keep-alive\r\n\r\n"),
5467 };
5468
5469 // Identical to data_writes1[]. The AuthHandler encounters a
5470 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5471 // transaction procceds without an authorization header.
5472 MockWrite data_writes2[] = {
5473 MockWrite("GET / HTTP/1.1\r\n"
5474 "Host: www.example.org\r\n"
5475 "Connection: keep-alive\r\n\r\n"),
5476 };
5477
5478 MockRead data_reads2[] = {
5479 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5480 "WWW-Authenticate: Mock\r\n"
5481 "Connection: keep-alive\r\n\r\n"),
5482 };
5483
5484 MockWrite data_writes3[] = {
5485 MockWrite("GET / HTTP/1.1\r\n"
5486 "Host: www.example.org\r\n"
5487 "Connection: keep-alive\r\n"
5488 "Authorization: auth_token\r\n\r\n"),
5489 };
5490
5491 MockRead data_reads3[] = {
5492 MockRead("HTTP/1.1 200 OK\r\n"
5493 "Content-Length: 5\r\n"
5494 "Content-Type: text/plain\r\n"
5495 "Connection: keep-alive\r\n\r\n"
5496 "Hello"),
5497 };
5498
Ryan Sleevib8d7ea02018-05-07 20:01:015499 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165500 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5501
Ryan Sleevib8d7ea02018-05-07 20:01:015502 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165503 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5504
Ryan Sleevib8d7ea02018-05-07 20:01:015505 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165506 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5507
bnc87dcefc2017-05-25 12:47:585508 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195509 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165510
5511 TestCompletionCallback callback;
5512 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5513 EXPECT_THAT(callback.GetResult(rv), IsOk());
5514
5515 const HttpResponseInfo* response = trans->GetResponseInfo();
5516 ASSERT_TRUE(response);
5517 ASSERT_TRUE(response->headers);
5518 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5519
5520 // The following three tests assert that an authentication challenge was
5521 // received and that the stack is ready to respond to the challenge using
5522 // ambient credentials.
5523 EXPECT_EQ(401, response->headers->response_code());
5524 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585525 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165526
5527 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5528 EXPECT_THAT(callback.GetResult(rv), IsOk());
5529 response = trans->GetResponseInfo();
5530 ASSERT_TRUE(response);
5531 ASSERT_TRUE(response->headers);
5532
5533 // The following three tests assert that an authentication challenge was
5534 // received and that the stack needs explicit credentials before it is ready
5535 // to respond to the challenge.
5536 EXPECT_EQ(401, response->headers->response_code());
5537 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585538 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165539
5540 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5541 EXPECT_THAT(callback.GetResult(rv), IsOk());
5542 response = trans->GetResponseInfo();
5543 ASSERT_TRUE(response);
5544 ASSERT_TRUE(response->headers);
5545 EXPECT_EQ(200, response->headers->response_code());
5546
5547 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115548 session->CloseAllConnections(ERR_FAILED, "Very good reason");
asankae2257db2016-10-11 22:03:165549}
5550
Matt Menked1eb6d42018-01-17 04:54:065551// Proxy resolver that returns a proxy with the same host and port for different
5552// schemes, based on the path of the URL being requests.
5553class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5554 public:
5555 SameProxyWithDifferentSchemesProxyResolver() {}
5556 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5557
5558 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
5559
5560 static HostPortPair ProxyHostPortPair() {
5561 return HostPortPair::FromString(ProxyHostPortPairAsString());
5562 }
5563
5564 // ProxyResolver implementation.
5565 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:395566 const NetworkIsolationKey& network_isolation_key,
Matt Menked1eb6d42018-01-17 04:54:065567 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175568 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065569 std::unique_ptr<Request>* request,
5570 const NetLogWithSource& /*net_log*/) override {
5571 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575572 results->set_traffic_annotation(
5573 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065574 if (url.path() == "/socks4") {
5575 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5576 return OK;
5577 }
5578 if (url.path() == "/socks5") {
5579 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5580 return OK;
5581 }
5582 if (url.path() == "/http") {
5583 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5584 return OK;
5585 }
5586 if (url.path() == "/https") {
5587 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5588 return OK;
5589 }
Matt Menkee8648fa2019-01-17 16:47:075590 if (url.path() == "/https_trusted") {
5591 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5592 ProxyHostPortPair(),
5593 true /* is_trusted_proxy */));
5594 return OK;
5595 }
Matt Menked1eb6d42018-01-17 04:54:065596 NOTREACHED();
5597 return ERR_NOT_IMPLEMENTED;
5598 }
5599
5600 private:
5601 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5602};
5603
5604class SameProxyWithDifferentSchemesProxyResolverFactory
5605 : public ProxyResolverFactory {
5606 public:
5607 SameProxyWithDifferentSchemesProxyResolverFactory()
5608 : ProxyResolverFactory(false) {}
5609
Lily Houghton99597862018-03-07 16:40:425610 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5611 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175612 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425613 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065614 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5615 return OK;
5616 }
5617
5618 private:
5619 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5620};
5621
5622// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075623// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065624// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5625// request to foo.com using proxy.com as an HTTP proxy.
5626TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495627 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565628 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:495629 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5630 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5631 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
5632 nullptr);
Matt Menked1eb6d42018-01-17 04:54:065633
5634 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5635
5636 MockWrite socks_writes[] = {
5637 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5638 kSOCKS4OkRequestLocalHostPort80Length),
5639 MockWrite(SYNCHRONOUS,
5640 "GET /socks4 HTTP/1.1\r\n"
5641 "Host: test\r\n"
5642 "Connection: keep-alive\r\n\r\n"),
5643 };
5644 MockRead socks_reads[] = {
5645 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5646 MockRead("HTTP/1.0 200 OK\r\n"
5647 "Connection: keep-alive\r\n"
5648 "Content-Length: 15\r\n\r\n"
5649 "SOCKS4 Response"),
5650 };
Ryan Sleevib8d7ea02018-05-07 20:01:015651 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065652 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5653
5654 const char kSOCKS5Request[] = {
5655 0x05, // Version
5656 0x01, // Command (CONNECT)
5657 0x00, // Reserved
5658 0x03, // Address type (DOMAINNAME)
5659 0x04, // Length of domain (4)
5660 't', 'e', 's', 't', // Domain string
5661 0x00, 0x50, // 16-bit port (80)
5662 };
5663 MockWrite socks5_writes[] = {
5664 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245665 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065666 MockWrite(SYNCHRONOUS,
5667 "GET /socks5 HTTP/1.1\r\n"
5668 "Host: test\r\n"
5669 "Connection: keep-alive\r\n\r\n"),
5670 };
5671 MockRead socks5_reads[] = {
5672 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5673 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5674 MockRead("HTTP/1.0 200 OK\r\n"
5675 "Connection: keep-alive\r\n"
5676 "Content-Length: 15\r\n\r\n"
5677 "SOCKS5 Response"),
5678 };
Ryan Sleevib8d7ea02018-05-07 20:01:015679 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065680 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5681
5682 MockWrite http_writes[] = {
5683 MockWrite(SYNCHRONOUS,
5684 "GET http://test/http HTTP/1.1\r\n"
5685 "Host: test\r\n"
5686 "Proxy-Connection: keep-alive\r\n\r\n"),
5687 };
5688 MockRead http_reads[] = {
5689 MockRead("HTTP/1.1 200 OK\r\n"
5690 "Proxy-Connection: keep-alive\r\n"
5691 "Content-Length: 13\r\n\r\n"
5692 "HTTP Response"),
5693 };
Ryan Sleevib8d7ea02018-05-07 20:01:015694 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065695 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5696
5697 MockWrite https_writes[] = {
5698 MockWrite(SYNCHRONOUS,
5699 "GET http://test/https HTTP/1.1\r\n"
5700 "Host: test\r\n"
5701 "Proxy-Connection: keep-alive\r\n\r\n"),
5702 };
5703 MockRead https_reads[] = {
5704 MockRead("HTTP/1.1 200 OK\r\n"
5705 "Proxy-Connection: keep-alive\r\n"
5706 "Content-Length: 14\r\n\r\n"
5707 "HTTPS Response"),
5708 };
Ryan Sleevib8d7ea02018-05-07 20:01:015709 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065710 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5711 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5713
Matt Menkee8648fa2019-01-17 16:47:075714 MockWrite https_trusted_writes[] = {
5715 MockWrite(SYNCHRONOUS,
5716 "GET http://test/https_trusted HTTP/1.1\r\n"
5717 "Host: test\r\n"
5718 "Proxy-Connection: keep-alive\r\n\r\n"),
5719 };
5720 MockRead https_trusted_reads[] = {
5721 MockRead("HTTP/1.1 200 OK\r\n"
5722 "Proxy-Connection: keep-alive\r\n"
5723 "Content-Length: 22\r\n\r\n"
5724 "HTTPS Trusted Response"),
5725 };
5726 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5727 https_trusted_writes);
5728 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5729 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5730 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5731
Matt Menked1eb6d42018-01-17 04:54:065732 struct TestCase {
5733 GURL url;
5734 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075735 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065736 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075737 int expected_idle_socks4_sockets;
5738 int expected_idle_socks5_sockets;
5739 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5740 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065741 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075742 int expected_idle_https_sockets;
5743 // How many idle sockets there should be in the HTTPS proxy socket pool with
5744 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5745 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065746 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075747 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5748 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5749 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5750 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5751 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5752 1},
Matt Menked1eb6d42018-01-17 04:54:065753 };
5754
5755 for (const auto& test_case : kTestCases) {
5756 HttpRequestInfo request;
5757 request.method = "GET";
5758 request.url = test_case.url;
Ramin Halavatib5e433e2018-02-07 07:41:105759 request.traffic_annotation =
5760 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065761 std::unique_ptr<HttpNetworkTransaction> trans =
5762 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5763 session.get());
5764 TestCompletionCallback callback;
5765 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5766 EXPECT_THAT(callback.GetResult(rv), IsOk());
5767
5768 const HttpResponseInfo* response = trans->GetResponseInfo();
5769 ASSERT_TRUE(response);
5770 ASSERT_TRUE(response->headers);
5771 EXPECT_EQ(200, response->headers->response_code());
5772 std::string response_data;
5773 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5774 EXPECT_EQ(test_case.expected_response, response_data);
5775
5776 // Return the socket to the socket pool, so can make sure it's not used for
5777 // the next requests.
5778 trans.reset();
5779 base::RunLoop().RunUntilIdle();
5780
5781 // Check the number of idle sockets in the pool, to make sure that used
5782 // sockets are indeed being returned to the socket pool. If each request
5783 // doesn't return an idle socket to the pool, the test would incorrectly
5784 // pass.
Matt Menkee8648fa2019-01-17 16:47:075785 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5786 session
Matt Menked23ab952019-03-06 00:24:405787 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075788 HttpNetworkSession::NORMAL_SOCKET_POOL,
5789 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5790 SameProxyWithDifferentSchemesProxyResolver::
5791 ProxyHostPortPair()))
5792 ->IdleSocketCount());
5793 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5794 session
Matt Menked23ab952019-03-06 00:24:405795 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075796 HttpNetworkSession::NORMAL_SOCKET_POOL,
5797 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5798 SameProxyWithDifferentSchemesProxyResolver::
5799 ProxyHostPortPair()))
5800 ->IdleSocketCount());
5801 EXPECT_EQ(test_case.expected_idle_http_sockets,
5802 session
Matt Menked23ab952019-03-06 00:24:405803 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075804 HttpNetworkSession::NORMAL_SOCKET_POOL,
5805 ProxyServer(ProxyServer::SCHEME_HTTP,
5806 SameProxyWithDifferentSchemesProxyResolver::
5807 ProxyHostPortPair()))
5808 ->IdleSocketCount());
5809 EXPECT_EQ(test_case.expected_idle_https_sockets,
5810 session
Matt Menked23ab952019-03-06 00:24:405811 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075812 HttpNetworkSession::NORMAL_SOCKET_POOL,
5813 ProxyServer(ProxyServer::SCHEME_HTTPS,
5814 SameProxyWithDifferentSchemesProxyResolver::
5815 ProxyHostPortPair()))
5816 ->IdleSocketCount());
5817 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5818 session
Matt Menked23ab952019-03-06 00:24:405819 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075820 HttpNetworkSession::NORMAL_SOCKET_POOL,
5821 ProxyServer(ProxyServer::SCHEME_HTTPS,
5822 SameProxyWithDifferentSchemesProxyResolver::
5823 ProxyHostPortPair(),
5824 true /* is_trusted_proxy */))
5825 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065826 }
5827}
5828
[email protected]029c83b62013-01-24 05:28:205829// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015830TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205831 HttpRequestInfo request1;
5832 request1.method = "GET";
bncce36dca22015-04-21 22:11:235833 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105834 request1.traffic_annotation =
5835 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205836
5837 HttpRequestInfo request2;
5838 request2.method = "GET";
bncce36dca22015-04-21 22:11:235839 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105840 request2.traffic_annotation =
5841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205842
5843 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:565844 session_deps_.proxy_resolution_service =
5845 ConfiguredProxyResolutionService::CreateFixed(
5846 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145847 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075848 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205850
5851 // Since we have proxy, should try to establish tunnel.
5852 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175853 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5854 "Host: www.example.org:443\r\n"
5855 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205856
rsleevidb16bb02015-11-12 23:47:175857 MockWrite("GET /1 HTTP/1.1\r\n"
5858 "Host: www.example.org\r\n"
5859 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205860
rsleevidb16bb02015-11-12 23:47:175861 MockWrite("GET /2 HTTP/1.1\r\n"
5862 "Host: www.example.org\r\n"
5863 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205864 };
5865
5866 // The proxy responds to the connect with a 407, using a persistent
5867 // connection.
5868 MockRead data_reads1[] = {
5869 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5870
5871 MockRead("HTTP/1.1 200 OK\r\n"),
5872 MockRead("Content-Length: 1\r\n\r\n"),
5873 MockRead(SYNCHRONOUS, "1"),
5874
5875 MockRead("HTTP/1.1 200 OK\r\n"),
5876 MockRead("Content-Length: 2\r\n\r\n"),
5877 MockRead(SYNCHRONOUS, "22"),
5878 };
5879
Ryan Sleevib8d7ea02018-05-07 20:01:015880 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075881 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205882 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205884
5885 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585886 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195887 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205888
5889 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015890 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205891
5892 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015893 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205894
5895 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525896 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475897 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525898 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205899 EXPECT_EQ(1, response1->headers->GetContentLength());
5900
5901 LoadTimingInfo load_timing_info1;
5902 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5903 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5904
5905 trans1.reset();
5906
5907 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585908 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195909 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205910
5911 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205913
5914 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015915 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205916
5917 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525918 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475919 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525920 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205921 EXPECT_EQ(2, response2->headers->GetContentLength());
5922
5923 LoadTimingInfo load_timing_info2;
5924 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5925 TestLoadTimingReused(load_timing_info2);
5926
5927 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5928
5929 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:115930 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:205931}
5932
5933// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015934TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205935 HttpRequestInfo request1;
5936 request1.method = "GET";
bncce36dca22015-04-21 22:11:235937 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105938 request1.traffic_annotation =
5939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205940
5941 HttpRequestInfo request2;
5942 request2.method = "GET";
bncce36dca22015-04-21 22:11:235943 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105944 request2.traffic_annotation =
5945 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205946
5947 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595948 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565949 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495950 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145951 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075952 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095953 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205954
5955 // Since we have proxy, should try to establish tunnel.
5956 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175957 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5958 "Host: www.example.org:443\r\n"
5959 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205960
rsleevidb16bb02015-11-12 23:47:175961 MockWrite("GET /1 HTTP/1.1\r\n"
5962 "Host: www.example.org\r\n"
5963 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205964
rsleevidb16bb02015-11-12 23:47:175965 MockWrite("GET /2 HTTP/1.1\r\n"
5966 "Host: www.example.org\r\n"
5967 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205968 };
5969
5970 // The proxy responds to the connect with a 407, using a persistent
5971 // connection.
5972 MockRead data_reads1[] = {
5973 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5974
5975 MockRead("HTTP/1.1 200 OK\r\n"),
5976 MockRead("Content-Length: 1\r\n\r\n"),
5977 MockRead(SYNCHRONOUS, "1"),
5978
5979 MockRead("HTTP/1.1 200 OK\r\n"),
5980 MockRead("Content-Length: 2\r\n\r\n"),
5981 MockRead(SYNCHRONOUS, "22"),
5982 };
5983
Ryan Sleevib8d7ea02018-05-07 20:01:015984 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075985 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205986 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205988
5989 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585990 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195991 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205992
5993 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015994 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205995
5996 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015997 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205998
5999 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:526000 ASSERT_TRUE(response1);
6001 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:206002 EXPECT_EQ(1, response1->headers->GetContentLength());
6003
6004 LoadTimingInfo load_timing_info1;
6005 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6006 TestLoadTimingNotReusedWithPac(load_timing_info1,
6007 CONNECT_TIMING_HAS_SSL_TIMES);
6008
6009 trans1.reset();
6010
6011 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:586012 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196013 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206014
6015 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206017
6018 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016019 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206020
6021 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:526022 ASSERT_TRUE(response2);
6023 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:206024 EXPECT_EQ(2, response2->headers->GetContentLength());
6025
6026 LoadTimingInfo load_timing_info2;
6027 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6028 TestLoadTimingReusedWithPac(load_timing_info2);
6029
6030 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6031
6032 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:116033 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:206034}
6035
Matt Menke8045afd2019-11-14 20:31:196036// Make sure that NetworkIsolationKeys are passed down to the proxy layer.
6037TEST_F(HttpNetworkTransactionTest, ProxyResolvedWithNetworkIsolationKey) {
6038 const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
6039 const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
6040
6041 ProxyConfig proxy_config;
6042 proxy_config.set_auto_detect(true);
6043 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6044
6045 CapturingProxyResolver capturing_proxy_resolver;
6046 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6047 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566048 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke8045afd2019-11-14 20:31:196049 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6050 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6051 std::make_unique<CapturingProxyResolverFactory>(
6052 &capturing_proxy_resolver),
6053 nullptr);
6054
6055 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6056
6057 // No need to continue with the network request - proxy resolution occurs
6058 // before establishing a data.
6059 StaticSocketDataProvider data{base::span<MockRead>(),
6060 base::span<MockWrite>()};
6061 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
6062 session_deps_.socket_factory->AddSocketDataProvider(&data);
6063
6064 // Run first request until an auth challenge is observed.
6065 HttpRequestInfo request;
6066 request.method = "GET";
6067 request.url = GURL("http://foo.test/");
6068 request.traffic_annotation =
6069 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6070 HttpNetworkTransaction trans(LOWEST, session.get());
6071 TestCompletionCallback callback;
6072 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6073 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
6074}
6075
dalyk6d7a8c52019-12-18 21:43:016076// Test that a failure in resolving the proxy hostname is retrievable.
6077TEST_F(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
6078 HttpRequestInfo request;
6079 request.method = "GET";
6080 request.url = GURL("http://www.example.org/");
6081 request.traffic_annotation =
6082 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6083
6084 RecordingTestNetLog log;
6085 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566086 session_deps_.proxy_resolution_service =
6087 ConfiguredProxyResolutionService::CreateFixed(
6088 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
dalyk6d7a8c52019-12-18 21:43:016089 MockHostResolver* resolver = new MockHostResolver();
6090 resolver->rules()->AddSimulatedTimeoutFailure("proxy");
6091 session_deps_.net_log = &log;
6092 session_deps_.host_resolver.reset(resolver);
6093 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6094 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6095 TestCompletionCallback callback;
6096
6097 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6099 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
6100
6101 const HttpResponseInfo* response = trans.GetResponseInfo();
6102 ASSERT_TRUE(response);
6103 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
6104}
6105
[email protected]2df19bb2010-08-25 20:13:466106// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016107TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276108 HttpRequestInfo request;
6109 request.method = "GET";
bncce36dca22015-04-21 22:11:236110 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106111 request.traffic_annotation =
6112 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276113
[email protected]2df19bb2010-08-25 20:13:466114 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566115 session_deps_.proxy_resolution_service =
6116 ConfiguredProxyResolutionService::CreateFixed(
6117 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146118 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076119 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096120 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466121
[email protected]2df19bb2010-08-25 20:13:466122 // Since we have proxy, should use full url
6123 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236124 MockWrite(
6125 "GET http://www.example.org/ HTTP/1.1\r\n"
6126 "Host: www.example.org\r\n"
6127 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466128 };
6129
6130 MockRead data_reads1[] = {
6131 MockRead("HTTP/1.1 200 OK\r\n"),
6132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6133 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066134 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466135 };
6136
Ryan Sleevib8d7ea02018-05-07 20:01:016137 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076138 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066139 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076140 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466141
[email protected]49639fa2011-12-20 23:22:416142 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466143
bnc691fda62016-08-12 00:43:166144 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506145
bnc691fda62016-08-12 00:43:166146 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016147 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466148
6149 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016150 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466151
[email protected]58e32bb2013-01-21 18:23:256152 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166153 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256154 TestLoadTimingNotReused(load_timing_info,
6155 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6156
bnc691fda62016-08-12 00:43:166157 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526158 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466159
tbansal2ecbbc72016-10-06 17:15:476160 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466161 EXPECT_TRUE(response->headers->IsKeepAlive());
6162 EXPECT_EQ(200, response->headers->response_code());
6163 EXPECT_EQ(100, response->headers->GetContentLength());
6164 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6165
6166 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586167 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466168}
6169
[email protected]7642b5ae2010-09-01 20:55:176170// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016171TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276172 HttpRequestInfo request;
6173 request.method = "GET";
bncce36dca22015-04-21 22:11:236174 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106175 request.traffic_annotation =
6176 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276177
[email protected]7642b5ae2010-09-01 20:55:176178 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566179 session_deps_.proxy_resolution_service =
6180 ConfiguredProxyResolutionService::CreateFixed(
6181 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146182 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076183 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096184 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176185
bncce36dca22015-04-21 22:11:236186 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136187 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456188 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416189 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176190
Ryan Hamilton0239aac2018-05-19 00:03:136191 spdy::SpdySerializedFrame resp(
6192 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6193 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176194 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416195 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176196 };
6197
Ryan Sleevib8d7ea02018-05-07 20:01:016198 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076199 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176200
[email protected]8ddf8322012-02-23 18:08:066201 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366202 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076203 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176204
[email protected]49639fa2011-12-20 23:22:416205 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176206
bnc691fda62016-08-12 00:43:166207 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506208
bnc691fda62016-08-12 00:43:166209 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176211
6212 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016213 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176214
[email protected]58e32bb2013-01-21 18:23:256215 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166216 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256217 TestLoadTimingNotReused(load_timing_info,
6218 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6219
bnc691fda62016-08-12 00:43:166220 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526221 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476222 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526223 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026224 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176225
6226 std::string response_data;
bnc691fda62016-08-12 00:43:166227 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236228 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176229}
6230
[email protected]1c173852014-06-19 12:51:506231// Verifies that a session which races and wins against the owning transaction
6232// (completing prior to host resolution), doesn't fail the transaction.
6233// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016234TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506235 HttpRequestInfo request;
6236 request.method = "GET";
bncce36dca22015-04-21 22:11:236237 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106238 request.traffic_annotation =
6239 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506240
6241 // Configure SPDY proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566242 session_deps_.proxy_resolution_service =
6243 ConfiguredProxyResolutionService::CreateFixed(
6244 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146245 RecordingBoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506246 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096247 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506248
bncce36dca22015-04-21 22:11:236249 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136250 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456251 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416252 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506253
Raul Tambre94493c652019-03-11 17:18:356254 spdy::SpdySerializedFrame resp(
6255 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136256 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506257 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416258 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506259 };
6260
Ryan Sleevib8d7ea02018-05-07 20:01:016261 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506262 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6263
6264 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366265 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506266 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6267
6268 TestCompletionCallback callback1;
6269
bnc691fda62016-08-12 00:43:166270 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506271
6272 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506273 session_deps_.host_resolver->set_ondemand_mode(true);
6274
bnc691fda62016-08-12 00:43:166275 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506277
6278 // Race a session to the proxy, which completes first.
6279 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046280 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116281 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346282 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6283 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506284 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526285 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506286
6287 // Unstall the resolution begun by the transaction.
6288 session_deps_.host_resolver->set_ondemand_mode(true);
6289 session_deps_.host_resolver->ResolveAllPending();
6290
6291 EXPECT_FALSE(callback1.have_result());
6292 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016293 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506294
bnc691fda62016-08-12 00:43:166295 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526296 ASSERT_TRUE(response);
6297 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026298 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506299
6300 std::string response_data;
bnc691fda62016-08-12 00:43:166301 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506302 EXPECT_EQ(kUploadData, response_data);
6303}
6304
[email protected]dc7bd1c52010-11-12 00:01:136305// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016306TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276307 HttpRequestInfo request;
6308 request.method = "GET";
bncce36dca22015-04-21 22:11:236309 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106310 request.traffic_annotation =
6311 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276312
[email protected]79cb5c12011-09-12 13:12:046313 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566314 session_deps_.proxy_resolution_service =
6315 ConfiguredProxyResolutionService::CreateFixed(
6316 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146317 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076318 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096319 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136320
[email protected]dc7bd1c52010-11-12 00:01:136321 // The first request will be a bare GET, the second request will be a
6322 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456323 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136324 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486325 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386326 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136327 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466328 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136329 };
Ryan Hamilton0239aac2018-05-19 00:03:136330 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246331 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486332 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136333 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416334 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136335 };
6336
6337 // The first response is a 407 proxy authentication challenge, and the second
6338 // response will be a 200 response since the second request includes a valid
6339 // Authorization header.
6340 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466341 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136342 };
Ryan Hamilton0239aac2018-05-19 00:03:136343 spdy::SpdySerializedFrame resp_authentication(
6344 spdy_util_.ConstructSpdyReplyError(
6345 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246346 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136347 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416348 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136349 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356350 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136351 spdy::SpdySerializedFrame body_data(
6352 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136353 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416354 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466355 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416356 CreateMockRead(resp_data, 4),
6357 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136358 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136359 };
6360
Ryan Sleevib8d7ea02018-05-07 20:01:016361 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076362 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136363
[email protected]8ddf8322012-02-23 18:08:066364 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366365 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076366 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136367
[email protected]49639fa2011-12-20 23:22:416368 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136369
bnc691fda62016-08-12 00:43:166370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136371
bnc691fda62016-08-12 00:43:166372 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016373 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136374
6375 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016376 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136377
bnc691fda62016-08-12 00:43:166378 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136379
wezca1070932016-05-26 20:30:526380 ASSERT_TRUE(response);
6381 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136382 EXPECT_EQ(407, response->headers->response_code());
6383 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586384 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136385
[email protected]49639fa2011-12-20 23:22:416386 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136387
bnc691fda62016-08-12 00:43:166388 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136390
6391 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016392 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136393
bnc691fda62016-08-12 00:43:166394 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136395
wezca1070932016-05-26 20:30:526396 ASSERT_TRUE(response_restart);
6397 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136398 EXPECT_EQ(200, response_restart->headers->response_code());
6399 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586400 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136401}
6402
[email protected]d9da5fe2010-10-13 22:37:166403// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016404TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276405 HttpRequestInfo request;
6406 request.method = "GET";
bncce36dca22015-04-21 22:11:236407 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106408 request.traffic_annotation =
6409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276410
[email protected]d9da5fe2010-10-13 22:37:166411 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566412 session_deps_.proxy_resolution_service =
6413 ConfiguredProxyResolutionService::CreateFixed(
6414 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146415 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076416 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096417 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166418
bnc691fda62016-08-12 00:43:166419 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166420
bncce36dca22015-04-21 22:11:236421 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136422 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046423 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6424 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236425 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166426
bncce36dca22015-04-21 22:11:236427 const char get[] =
6428 "GET / HTTP/1.1\r\n"
6429 "Host: www.example.org\r\n"
6430 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136431 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196432 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136433 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356434 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166435 const char resp[] = "HTTP/1.1 200 OK\r\n"
6436 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136437 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196438 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136439 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196440 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136441 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416442 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046443
6444 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416445 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6446 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046447 };
6448
[email protected]d9da5fe2010-10-13 22:37:166449 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416450 CreateMockRead(conn_resp, 1, ASYNC),
6451 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6452 CreateMockRead(wrapped_body, 4, ASYNC),
6453 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136454 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166455 };
6456
Ryan Sleevib8d7ea02018-05-07 20:01:016457 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076458 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166459
[email protected]8ddf8322012-02-23 18:08:066460 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366461 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076462 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066463 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166465
[email protected]49639fa2011-12-20 23:22:416466 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166467
bnc691fda62016-08-12 00:43:166468 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166470
6471 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016472 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166473
[email protected]58e32bb2013-01-21 18:23:256474 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166475 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256476 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6477
bnc691fda62016-08-12 00:43:166478 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526479 ASSERT_TRUE(response);
6480 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166481 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6482
6483 std::string response_data;
bnc691fda62016-08-12 00:43:166484 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166485 EXPECT_EQ("1234567890", response_data);
6486}
6487
6488// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016489TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6490 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386491
[email protected]cb9bf6ca2011-01-28 13:15:276492 HttpRequestInfo request;
6493 request.method = "GET";
bncce36dca22015-04-21 22:11:236494 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106495 request.traffic_annotation =
6496 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276497
[email protected]d9da5fe2010-10-13 22:37:166498 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566499 session_deps_.proxy_resolution_service =
6500 ConfiguredProxyResolutionService::CreateFixed(
6501 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146502 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076503 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096504 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166505
bnc691fda62016-08-12 00:43:166506 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166507
bncce36dca22015-04-21 22:11:236508 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136509 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046510 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6511 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236512 // fetch https://www.example.org/ via SPDY
6513 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136514 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496515 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136516 spdy::SpdySerializedFrame wrapped_get(
6517 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6518 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356519 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136520 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356521 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136522 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026523 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136524 spdy::SpdySerializedFrame body(
6525 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6526 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026527 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136528 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416529 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136530 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416531 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046532
6533 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416534 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6535 CreateMockWrite(window_update_get_resp, 6),
6536 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046537 };
6538
[email protected]d9da5fe2010-10-13 22:37:166539 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416540 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096541 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416542 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6543 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136544 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166545 };
6546
Ryan Sleevib8d7ea02018-05-07 20:01:016547 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076548 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166549
[email protected]8ddf8322012-02-23 18:08:066550 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366551 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076552 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066553 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366554 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166556
[email protected]49639fa2011-12-20 23:22:416557 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166558
bnc691fda62016-08-12 00:43:166559 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166561
rch32320842015-05-16 15:57:096562 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556563 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096564 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596565 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166566 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016567 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166568
[email protected]58e32bb2013-01-21 18:23:256569 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166570 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256571 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6572
bnc691fda62016-08-12 00:43:166573 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526574 ASSERT_TRUE(response);
6575 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026576 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166577
6578 std::string response_data;
bnc691fda62016-08-12 00:43:166579 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236580 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166581}
6582
6583// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016584TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276585 HttpRequestInfo request;
6586 request.method = "GET";
bncce36dca22015-04-21 22:11:236587 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106588 request.traffic_annotation =
6589 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276590
[email protected]d9da5fe2010-10-13 22:37:166591 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566592 session_deps_.proxy_resolution_service =
6593 ConfiguredProxyResolutionService::CreateFixed(
6594 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146595 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076596 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096597 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166598
bnc691fda62016-08-12 00:43:166599 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166600
bncce36dca22015-04-21 22:11:236601 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136602 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046603 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6604 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136605 spdy::SpdySerializedFrame get(
6606 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166607
6608 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416609 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166610 };
6611
Ryan Hamilton0239aac2018-05-19 00:03:136612 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6613 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166614 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416615 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166616 };
6617
Ryan Sleevib8d7ea02018-05-07 20:01:016618 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076619 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166620
[email protected]8ddf8322012-02-23 18:08:066621 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366622 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066624 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366625 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076626 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166627
[email protected]49639fa2011-12-20 23:22:416628 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166629
bnc691fda62016-08-12 00:43:166630 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166632
6633 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016634 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166635
ttuttle960fcbf2016-04-19 13:26:326636 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166637}
6638
Matt Menkecb2cd0982018-12-19 17:54:046639// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246640// is observed, but does exist by the time auth credentials are provided. In
6641// this case, auth and SSL are fully negotated on the second request, but then
6642// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046643TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6644 ProxyConfig proxy_config;
6645 proxy_config.set_auto_detect(true);
6646 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6647
6648 CapturingProxyResolver capturing_proxy_resolver;
6649 capturing_proxy_resolver.set_proxy_server(
6650 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6651 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566652 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menkecb2cd0982018-12-19 17:54:046653 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6654 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6655 std::make_unique<CapturingProxyResolverFactory>(
6656 &capturing_proxy_resolver),
6657 nullptr);
6658
6659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6660
6661 const char kMyUrl[] = "https://www.example.org/";
6662 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6663 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356664 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046665 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6666
6667 spdy_util_.UpdateWithStreamDestruction(1);
6668 spdy::SpdySerializedFrame get2(
6669 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6670 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356671 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046672 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6673
6674 MockWrite auth_challenge_writes[] = {
6675 MockWrite(ASYNC, 0,
6676 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6677 "Host: www.example.org:443\r\n"
6678 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246679 MockWrite(ASYNC, 2,
6680 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6681 "Host: www.example.org:443\r\n"
6682 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046683 };
6684
6685 MockRead auth_challenge_reads[] = {
6686 MockRead(ASYNC, 1,
6687 "HTTP/1.1 407 Authentication Required\r\n"
6688 "Content-Length: 0\r\n"
6689 "Proxy-Connection: close\r\n"
6690 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6691 };
6692
6693 MockWrite spdy_writes[] = {
6694 MockWrite(ASYNC, 0,
6695 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6696 "Host: www.example.org:443\r\n"
6697 "Proxy-Connection: keep-alive\r\n"
6698 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6699 CreateMockWrite(get, 2),
6700 CreateMockWrite(get2, 5),
6701 };
6702
6703 MockRead spdy_reads[] = {
6704 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6705 CreateMockRead(get_resp, 3, ASYNC),
6706 CreateMockRead(body, 4, ASYNC),
6707 CreateMockRead(get_resp2, 6, ASYNC),
6708 CreateMockRead(body2, 7, ASYNC),
6709
6710 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6711 };
6712
Matt Menke5062be22019-05-01 17:50:246713 MockWrite auth_response_writes_discarded_socket[] = {
6714 MockWrite(ASYNC, 0,
6715 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6716 "Host: www.example.org:443\r\n"
6717 "Proxy-Connection: keep-alive\r\n"
6718 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6719 };
6720
6721 MockRead auth_response_reads_discarded_socket[] = {
6722 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6723 };
6724
Matt Menkecb2cd0982018-12-19 17:54:046725 SequencedSocketData auth_challenge1(auth_challenge_reads,
6726 auth_challenge_writes);
6727 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6728
6729 SequencedSocketData auth_challenge2(auth_challenge_reads,
6730 auth_challenge_writes);
6731 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6732
6733 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6734 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6735
Matt Menke5062be22019-05-01 17:50:246736 SequencedSocketData auth_response_discarded_socket(
6737 auth_response_reads_discarded_socket,
6738 auth_response_writes_discarded_socket);
6739 session_deps_.socket_factory->AddSocketDataProvider(
6740 &auth_response_discarded_socket);
6741
Matt Menkecb2cd0982018-12-19 17:54:046742 SSLSocketDataProvider ssl(ASYNC, OK);
6743 ssl.next_proto = kProtoHTTP2;
6744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6745
Matt Menke5062be22019-05-01 17:50:246746 SSLSocketDataProvider ssl2(ASYNC, OK);
6747 ssl2.next_proto = kProtoHTTP2;
6748 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6749
Matt Menkecb2cd0982018-12-19 17:54:046750 TestCompletionCallback callback;
6751 std::string response_data;
6752
6753 // Run first request until an auth challenge is observed.
6754 HttpRequestInfo request1;
6755 request1.method = "GET";
6756 request1.url = GURL(kMyUrl);
6757 request1.traffic_annotation =
6758 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6759 HttpNetworkTransaction trans1(LOWEST, session.get());
6760 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6761 EXPECT_THAT(callback.GetResult(rv), IsOk());
6762 const HttpResponseInfo* response = trans1.GetResponseInfo();
6763 ASSERT_TRUE(response);
6764 ASSERT_TRUE(response->headers);
6765 EXPECT_EQ(407, response->headers->response_code());
6766 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586767 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046768
6769 // Run second request until an auth challenge is observed.
6770 HttpRequestInfo request2;
6771 request2.method = "GET";
6772 request2.url = GURL(kMyUrl);
6773 request2.traffic_annotation =
6774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6775 HttpNetworkTransaction trans2(LOWEST, session.get());
6776 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6777 EXPECT_THAT(callback.GetResult(rv), IsOk());
6778 response = trans2.GetResponseInfo();
6779 ASSERT_TRUE(response);
6780 ASSERT_TRUE(response->headers);
6781 EXPECT_EQ(407, response->headers->response_code());
6782 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586783 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046784
6785 // Now provide credentials for the first request, and wait for it to complete.
6786 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6787 rv = callback.GetResult(rv);
6788 EXPECT_THAT(rv, IsOk());
6789 response = trans1.GetResponseInfo();
6790 ASSERT_TRUE(response);
6791 ASSERT_TRUE(response->headers);
6792 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6793 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6794 EXPECT_EQ(kUploadData, response_data);
6795
6796 // Now provide credentials for the second request. It should notice the
6797 // existing session, and reuse it.
6798 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6799 EXPECT_THAT(callback.GetResult(rv), IsOk());
6800 response = trans2.GetResponseInfo();
6801 ASSERT_TRUE(response);
6802 ASSERT_TRUE(response->headers);
6803 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6804 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6805 EXPECT_EQ(kUploadData, response_data);
6806}
6807
[email protected]f6c63db52013-02-02 00:35:226808// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6809// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016810TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226811 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6812 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566813 session_deps_.proxy_resolution_service =
6814 ConfiguredProxyResolutionService::CreateFixed(
6815 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146816 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076817 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096818 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506819 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226820
6821 HttpRequestInfo request1;
6822 request1.method = "GET";
bncce36dca22015-04-21 22:11:236823 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226824 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106825 request1.traffic_annotation =
6826 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226827
6828 HttpRequestInfo request2;
6829 request2.method = "GET";
bncce36dca22015-04-21 22:11:236830 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226831 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106832 request2.traffic_annotation =
6833 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226834
bncce36dca22015-04-21 22:11:236835 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136836 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046837 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6838 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136839 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356840 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226841
bncce36dca22015-04-21 22:11:236842 // Fetch https://www.example.org/ via HTTP.
6843 const char get1[] =
6844 "GET / HTTP/1.1\r\n"
6845 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226846 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136847 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196848 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226849 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6850 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136851 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196852 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136853 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196854 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136855 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416856 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226857
bncce36dca22015-04-21 22:11:236858 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136859 spdy::SpdyHeaderBlock connect2_block;
6860 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6861 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6862 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046863 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6864 false));
[email protected]601e03f12014-04-06 16:26:396865
Ryan Hamilton0239aac2018-05-19 00:03:136866 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356867 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226868
bncce36dca22015-04-21 22:11:236869 // Fetch https://mail.example.org/ via HTTP.
6870 const char get2[] =
6871 "GET / HTTP/1.1\r\n"
6872 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226873 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136874 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196875 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226876 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6877 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136878 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196879 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136880 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196881 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226882
6883 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416884 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6885 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226886 };
6887
6888 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416889 CreateMockRead(conn_resp1, 1, ASYNC),
6890 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6891 CreateMockRead(wrapped_body1, 4, ASYNC),
6892 CreateMockRead(conn_resp2, 6, ASYNC),
6893 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6894 CreateMockRead(wrapped_body2, 9, ASYNC),
6895 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226896 };
6897
Ryan Sleevib8d7ea02018-05-07 20:01:016898 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506899 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226900
6901 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366902 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226904 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506905 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226906 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506907 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226908
6909 TestCompletionCallback callback;
6910
bnc691fda62016-08-12 00:43:166911 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206912 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016913 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226914
6915 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166916 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226917 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6918
bnc691fda62016-08-12 00:43:166919 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526920 ASSERT_TRUE(response);
6921 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226922 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6923
6924 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446925 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166926 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506927 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226928
bnc691fda62016-08-12 00:43:166929 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206930 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016931 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226932
6933 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166934 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226935 // Even though the SPDY connection is reused, a new tunnelled connection has
6936 // to be created, so the socket's load timing looks like a fresh connection.
6937 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6938
6939 // The requests should have different IDs, since they each are using their own
6940 // separate stream.
6941 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6942
bnc691fda62016-08-12 00:43:166943 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506944 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226945}
6946
6947// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6948// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016949TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226950 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6951 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566952 session_deps_.proxy_resolution_service =
6953 ConfiguredProxyResolutionService::CreateFixed(
6954 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146955 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076956 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096957 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506958 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226959
6960 HttpRequestInfo request1;
6961 request1.method = "GET";
bncce36dca22015-04-21 22:11:236962 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226963 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106964 request1.traffic_annotation =
6965 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226966
6967 HttpRequestInfo request2;
6968 request2.method = "GET";
bncce36dca22015-04-21 22:11:236969 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226970 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106971 request2.traffic_annotation =
6972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226973
bncce36dca22015-04-21 22:11:236974 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136975 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046976 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6977 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136978 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356979 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226980
bncce36dca22015-04-21 22:11:236981 // Fetch https://www.example.org/ via HTTP.
6982 const char get1[] =
6983 "GET / HTTP/1.1\r\n"
6984 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226985 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136986 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196987 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226988 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6989 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136990 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196991 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136992 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196993 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136994 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416995 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226996
bncce36dca22015-04-21 22:11:236997 // Fetch https://www.example.org/2 via HTTP.
6998 const char get2[] =
6999 "GET /2 HTTP/1.1\r\n"
7000 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227001 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137002 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:197003 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:227004 const char resp2[] = "HTTP/1.1 200 OK\r\n"
7005 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137006 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:197007 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:137008 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:197009 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:227010
7011 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417012 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
7013 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:227014 };
7015
7016 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417017 CreateMockRead(conn_resp1, 1, ASYNC),
7018 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:467019 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417020 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:467021 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417022 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:227023 };
7024
Ryan Sleevib8d7ea02018-05-07 20:01:017025 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507026 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227027
7028 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367029 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227031 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507032 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:227033
7034 TestCompletionCallback callback;
7035
bnc87dcefc2017-05-25 12:47:587036 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197037 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207038 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017039 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227040
7041 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017042 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227043
7044 LoadTimingInfo load_timing_info;
7045 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7046 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7047
7048 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527049 ASSERT_TRUE(response);
7050 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227051 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7052
7053 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447054 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:507055 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227056 trans.reset();
7057
bnc87dcefc2017-05-25 12:47:587058 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:197059 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207060 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017061 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227062
[email protected]f6c63db52013-02-02 00:35:227063 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017064 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227065
7066 LoadTimingInfo load_timing_info2;
7067 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
7068 TestLoadTimingReused(load_timing_info2);
7069
7070 // The requests should have the same ID.
7071 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7072
[email protected]90499482013-06-01 00:39:507073 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227074}
7075
7076// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
7077// Proxy to different servers.
bncd16676a2016-07-20 16:23:017078TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:227079 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567080 session_deps_.proxy_resolution_service =
7081 ConfiguredProxyResolutionService::CreateFixed(
7082 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147083 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077084 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097085 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507086 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227087
7088 HttpRequestInfo request1;
7089 request1.method = "GET";
bncce36dca22015-04-21 22:11:237090 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227091 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107092 request1.traffic_annotation =
7093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227094
7095 HttpRequestInfo request2;
7096 request2.method = "GET";
bncce36dca22015-04-21 22:11:237097 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227098 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107099 request2.traffic_annotation =
7100 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227101
bncce36dca22015-04-21 22:11:237102 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137103 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:237104 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137105 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:157106 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137107 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:357108 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:137109 spdy::SpdySerializedFrame body1(
7110 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:387111 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:227112
bncce36dca22015-04-21 22:11:237113 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137114 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:237115 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137116 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:157117 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137118 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357119 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137120 spdy::SpdySerializedFrame body2(
7121 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227122
7123 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417124 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227125 };
7126
7127 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417128 CreateMockRead(get_resp1, 1, ASYNC),
7129 CreateMockRead(body1, 2, ASYNC),
7130 CreateMockRead(get_resp2, 4, ASYNC),
7131 CreateMockRead(body2, 5, ASYNC),
7132 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227133 };
7134
Ryan Sleevib8d7ea02018-05-07 20:01:017135 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507136 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227137
7138 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367139 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507140 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227141
7142 TestCompletionCallback callback;
7143
bnc87dcefc2017-05-25 12:47:587144 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197145 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207146 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017147 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227148
7149 LoadTimingInfo load_timing_info;
7150 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7151 TestLoadTimingNotReused(load_timing_info,
7152 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7153
7154 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527155 ASSERT_TRUE(response);
7156 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027157 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227158
7159 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447160 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507161 rv = trans->Read(buf.get(), 256, callback.callback());
7162 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227163 // Delete the first request, so the second one can reuse the socket.
7164 trans.reset();
7165
bnc691fda62016-08-12 00:43:167166 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207167 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017168 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227169
7170 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167171 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227172 TestLoadTimingReused(load_timing_info2);
7173
7174 // The requests should have the same ID.
7175 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7176
bnc691fda62016-08-12 00:43:167177 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507178 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227179}
7180
Matt Menke2436b2f2018-12-11 18:07:117181// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7182// direct (non-proxied) request to the proxy server are not pooled, as that
7183// would break socket pool isolation.
7184TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7185 ProxyConfig proxy_config;
7186 proxy_config.set_auto_detect(true);
7187 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7188
7189 CapturingProxyResolver capturing_proxy_resolver;
7190 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567191 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117192 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7193 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7194 std::make_unique<CapturingProxyResolverFactory>(
7195 &capturing_proxy_resolver),
7196 nullptr);
7197
7198 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7199
7200 SpdyTestUtil spdy_util1;
7201 // CONNECT to www.example.org:443 via HTTP/2.
7202 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047203 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7204 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117205 // fetch https://www.example.org/ via HTTP/2.
7206 const char kMyUrl[] = "https://www.example.org/";
7207 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7208 spdy::SpdySerializedFrame wrapped_get(
7209 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7210 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357211 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117212 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357213 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117214 spdy::SpdySerializedFrame wrapped_get_resp(
7215 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7216 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7217 spdy::SpdySerializedFrame wrapped_body(
7218 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7219 spdy::SpdySerializedFrame window_update_get_resp(
7220 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7221 spdy::SpdySerializedFrame window_update_body(
7222 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7223
7224 MockWrite spdy_writes1[] = {
7225 CreateMockWrite(connect, 0),
7226 CreateMockWrite(wrapped_get, 2),
7227 CreateMockWrite(window_update_get_resp, 6),
7228 CreateMockWrite(window_update_body, 7),
7229 };
7230
7231 MockRead spdy_reads1[] = {
7232 CreateMockRead(conn_resp, 1, ASYNC),
7233 MockRead(ASYNC, ERR_IO_PENDING, 3),
7234 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7235 CreateMockRead(wrapped_body, 5, ASYNC),
7236 MockRead(ASYNC, 0, 8),
7237 };
7238
7239 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7240 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7241
7242 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7243 // a new pipe.
7244 SpdyTestUtil spdy_util2;
7245 spdy::SpdySerializedFrame req(
7246 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7247 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7248
7249 spdy::SpdySerializedFrame resp(
7250 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7251 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7252 MockRead spdy_reads2[] = {
7253 CreateMockRead(resp, 1),
7254 CreateMockRead(data, 2),
7255 MockRead(ASYNC, 0, 3),
7256 };
7257 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7258 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7259
7260 SSLSocketDataProvider ssl(ASYNC, OK);
7261 ssl.next_proto = kProtoHTTP2;
7262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7263 SSLSocketDataProvider ssl2(ASYNC, OK);
7264 ssl2.next_proto = kProtoHTTP2;
7265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7266 SSLSocketDataProvider ssl3(ASYNC, OK);
7267 ssl3.next_proto = kProtoHTTP2;
7268 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7269
7270 TestCompletionCallback callback;
7271 std::string response_data;
7272
7273 // Make a request using proxy:70 as a HTTP/2 proxy.
7274 capturing_proxy_resolver.set_proxy_server(
7275 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7276 HttpRequestInfo request1;
7277 request1.method = "GET";
7278 request1.url = GURL("https://www.example.org/");
7279 request1.traffic_annotation =
7280 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7281
7282 HttpNetworkTransaction trans1(LOWEST, session.get());
7283 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7284 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7285
7286 // Allow the SpdyProxyClientSocket's write callback to complete.
7287 base::RunLoop().RunUntilIdle();
7288 // Now allow the read of the response to complete.
7289 spdy_data1.Resume();
7290 rv = callback.WaitForResult();
7291 EXPECT_THAT(rv, IsOk());
7292
7293 const HttpResponseInfo* response = trans1.GetResponseInfo();
7294 ASSERT_TRUE(response);
7295 ASSERT_TRUE(response->headers);
7296 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7297
7298 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7299 EXPECT_EQ(kUploadData, response_data);
7300 RunUntilIdle();
7301
7302 // Make a direct HTTP/2 request to proxy:70.
7303 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7304 HttpRequestInfo request2;
7305 request2.method = "GET";
7306 request2.url = GURL("https://proxy:70/");
7307 request2.traffic_annotation =
7308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7309 HttpNetworkTransaction trans2(LOWEST, session.get());
7310 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7311 NetLogWithSource())),
7312 IsOk());
7313 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7314}
7315
7316// Same as above, but reverse request order, since the code to check for an
7317// existing session is different for tunnels and direct connections.
7318TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7319 // Configure against https proxy server "myproxy:80".
7320 ProxyConfig proxy_config;
7321 proxy_config.set_auto_detect(true);
7322 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7323
7324 CapturingProxyResolver capturing_proxy_resolver;
7325 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567326 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117327 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7328 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7329 std::make_unique<CapturingProxyResolverFactory>(
7330 &capturing_proxy_resolver),
7331 nullptr);
7332
7333 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7334 // Fetch https://proxy:70/ via HTTP/2.
7335 SpdyTestUtil spdy_util1;
7336 spdy::SpdySerializedFrame req(
7337 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7338 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7339
7340 spdy::SpdySerializedFrame resp(
7341 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7342 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7343 MockRead spdy_reads1[] = {
7344 CreateMockRead(resp, 1),
7345 CreateMockRead(data, 2),
7346 MockRead(ASYNC, 0, 3),
7347 };
7348 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7349 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7350
7351 SpdyTestUtil spdy_util2;
7352 // CONNECT to www.example.org:443 via HTTP/2.
7353 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047354 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7355 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117356 // fetch https://www.example.org/ via HTTP/2.
7357 const char kMyUrl[] = "https://www.example.org/";
7358 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7359 spdy::SpdySerializedFrame wrapped_get(
7360 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7361 spdy::SpdySerializedFrame conn_resp(
7362 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7363 spdy::SpdySerializedFrame get_resp(
7364 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7365 spdy::SpdySerializedFrame wrapped_get_resp(
7366 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7367 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7368 spdy::SpdySerializedFrame wrapped_body(
7369 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7370 spdy::SpdySerializedFrame window_update_get_resp(
7371 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7372 spdy::SpdySerializedFrame window_update_body(
7373 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7374
7375 MockWrite spdy_writes2[] = {
7376 CreateMockWrite(connect, 0),
7377 CreateMockWrite(wrapped_get, 2),
7378 CreateMockWrite(window_update_get_resp, 6),
7379 CreateMockWrite(window_update_body, 7),
7380 };
7381
7382 MockRead spdy_reads2[] = {
7383 CreateMockRead(conn_resp, 1, ASYNC),
7384 MockRead(ASYNC, ERR_IO_PENDING, 3),
7385 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7386 CreateMockRead(wrapped_body, 5, ASYNC),
7387 MockRead(ASYNC, 0, 8),
7388 };
7389
7390 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7391 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7392
7393 SSLSocketDataProvider ssl(ASYNC, OK);
7394 ssl.next_proto = kProtoHTTP2;
7395 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7396 SSLSocketDataProvider ssl2(ASYNC, OK);
7397 ssl2.next_proto = kProtoHTTP2;
7398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7399 SSLSocketDataProvider ssl3(ASYNC, OK);
7400 ssl3.next_proto = kProtoHTTP2;
7401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7402
7403 TestCompletionCallback callback;
7404 std::string response_data;
7405
7406 // Make a direct HTTP/2 request to proxy:70.
7407 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7408 HttpRequestInfo request1;
7409 request1.method = "GET";
7410 request1.url = GURL("https://proxy:70/");
7411 request1.traffic_annotation =
7412 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7413 HttpNetworkTransaction trans1(LOWEST, session.get());
7414 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7415 NetLogWithSource())),
7416 IsOk());
7417 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7418 RunUntilIdle();
7419
7420 // Make a request using proxy:70 as a HTTP/2 proxy.
7421 capturing_proxy_resolver.set_proxy_server(
7422 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7423 HttpRequestInfo request2;
7424 request2.method = "GET";
7425 request2.url = GURL("https://www.example.org/");
7426 request2.traffic_annotation =
7427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7428
7429 HttpNetworkTransaction trans2(LOWEST, session.get());
7430 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7432
7433 // Allow the SpdyProxyClientSocket's write callback to complete.
7434 base::RunLoop().RunUntilIdle();
7435 // Now allow the read of the response to complete.
7436 spdy_data2.Resume();
7437 rv = callback.WaitForResult();
7438 EXPECT_THAT(rv, IsOk());
7439
7440 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7441 ASSERT_TRUE(response2);
7442 ASSERT_TRUE(response2->headers);
7443 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7444
7445 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7446 EXPECT_EQ(kUploadData, response_data);
7447}
7448
[email protected]2df19bb2010-08-25 20:13:467449// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017450TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467451 HttpRequestInfo request;
7452 request.method = "GET";
bncce36dca22015-04-21 22:11:237453 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467454 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297455 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:107456 request.traffic_annotation =
7457 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467458
[email protected]79cb5c12011-09-12 13:12:047459 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567460 session_deps_.proxy_resolution_service =
7461 ConfiguredProxyResolutionService::CreateFixed(
7462 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147463 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077464 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097465 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277466
[email protected]2df19bb2010-08-25 20:13:467467 // Since we have proxy, should use full url
7468 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167469 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7470 "Host: www.example.org\r\n"
7471 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467472
bnc691fda62016-08-12 00:43:167473 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237474 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167475 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7476 "Host: www.example.org\r\n"
7477 "Proxy-Connection: keep-alive\r\n"
7478 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467479 };
7480
7481 // The proxy responds to the GET with a 407, using a persistent
7482 // connection.
7483 MockRead data_reads1[] = {
7484 // No credentials.
7485 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7486 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7487 MockRead("Proxy-Connection: keep-alive\r\n"),
7488 MockRead("Content-Length: 0\r\n\r\n"),
7489
7490 MockRead("HTTP/1.1 200 OK\r\n"),
7491 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7492 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067493 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467494 };
7495
Ryan Sleevib8d7ea02018-05-07 20:01:017496 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077497 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067498 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077499 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467500
[email protected]49639fa2011-12-20 23:22:417501 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467502
bnc691fda62016-08-12 00:43:167503 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507504
bnc691fda62016-08-12 00:43:167505 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017506 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467507
7508 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017509 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467510
[email protected]58e32bb2013-01-21 18:23:257511 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167512 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257513 TestLoadTimingNotReused(load_timing_info,
7514 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7515
bnc691fda62016-08-12 00:43:167516 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527517 ASSERT_TRUE(response);
7518 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467519 EXPECT_EQ(407, response->headers->response_code());
7520 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587521 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507522 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467523
[email protected]49639fa2011-12-20 23:22:417524 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467525
bnc691fda62016-08-12 00:43:167526 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017527 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467528
7529 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017530 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467531
[email protected]58e32bb2013-01-21 18:23:257532 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167533 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257534 // Retrying with HTTP AUTH is considered to be reusing a socket.
7535 TestLoadTimingReused(load_timing_info);
7536
bnc691fda62016-08-12 00:43:167537 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527538 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467539
7540 EXPECT_TRUE(response->headers->IsKeepAlive());
7541 EXPECT_EQ(200, response->headers->response_code());
7542 EXPECT_EQ(100, response->headers->GetContentLength());
7543 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507544 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467545
7546 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587547 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467548}
7549
[email protected]23e482282013-06-14 16:08:027550void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087551 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427552 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087553 request.method = "GET";
bncce36dca22015-04-21 22:11:237554 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107555 request.traffic_annotation =
7556 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087557
[email protected]cb9bf6ca2011-01-28 13:15:277558 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567559 session_deps_.proxy_resolution_service =
7560 ConfiguredProxyResolutionService::CreateFixed(
7561 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097562 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277563
[email protected]c744cf22009-02-27 07:28:087564 // Since we have proxy, should try to establish tunnel.
7565 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177566 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7567 "Host: www.example.org:443\r\n"
7568 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087569 };
7570
7571 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237572 status, MockRead("Content-Length: 10\r\n\r\n"),
7573 // No response body because the test stops reading here.
7574 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087575 };
7576
Ryan Sleevib8d7ea02018-05-07 20:01:017577 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077578 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087579
[email protected]49639fa2011-12-20 23:22:417580 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087581
bnc691fda62016-08-12 00:43:167582 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507583
tfarina42834112016-09-22 13:38:207584 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017585 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087586
7587 rv = callback.WaitForResult();
7588 EXPECT_EQ(expected_status, rv);
7589}
7590
[email protected]23e482282013-06-14 16:08:027591void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237592 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087593 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427594 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087595}
7596
bncd16676a2016-07-20 16:23:017597TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087598 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7599}
7600
bncd16676a2016-07-20 16:23:017601TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087602 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7603}
7604
bncd16676a2016-07-20 16:23:017605TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087606 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7607}
7608
bncd16676a2016-07-20 16:23:017609TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087610 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7611}
7612
bncd16676a2016-07-20 16:23:017613TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087614 ConnectStatusHelper(
7615 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7616}
7617
bncd16676a2016-07-20 16:23:017618TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087619 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7620}
7621
bncd16676a2016-07-20 16:23:017622TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087623 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7624}
7625
bncd16676a2016-07-20 16:23:017626TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087627 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7628}
7629
bncd16676a2016-07-20 16:23:017630TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087631 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7632}
7633
bncd16676a2016-07-20 16:23:017634TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087635 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7636}
7637
bncd16676a2016-07-20 16:23:017638TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087639 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7640}
7641
bncd16676a2016-07-20 16:23:017642TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087643 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7644}
7645
bncd16676a2016-07-20 16:23:017646TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087647 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7648}
7649
bncd16676a2016-07-20 16:23:017650TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087651 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7652}
7653
bncd16676a2016-07-20 16:23:017654TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087655 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7656}
7657
bncd16676a2016-07-20 16:23:017658TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087659 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7660}
7661
bncd16676a2016-07-20 16:23:017662TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377663 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7664}
7665
bncd16676a2016-07-20 16:23:017666TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087667 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7668}
7669
bncd16676a2016-07-20 16:23:017670TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087671 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7672}
7673
bncd16676a2016-07-20 16:23:017674TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087675 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7676}
7677
bncd16676a2016-07-20 16:23:017678TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087679 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7680}
7681
bncd16676a2016-07-20 16:23:017682TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087683 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7684}
7685
bncd16676a2016-07-20 16:23:017686TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087687 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7688}
7689
bncd16676a2016-07-20 16:23:017690TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087691 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7692}
7693
bncd16676a2016-07-20 16:23:017694TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087695 ConnectStatusHelperWithExpectedStatus(
7696 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547697 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087698}
7699
bncd16676a2016-07-20 16:23:017700TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087701 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7702}
7703
bncd16676a2016-07-20 16:23:017704TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087705 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7706}
7707
bncd16676a2016-07-20 16:23:017708TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087709 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7710}
7711
bncd16676a2016-07-20 16:23:017712TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087713 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7714}
7715
bncd16676a2016-07-20 16:23:017716TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087717 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7718}
7719
bncd16676a2016-07-20 16:23:017720TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087721 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7722}
7723
bncd16676a2016-07-20 16:23:017724TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087725 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7726}
7727
bncd16676a2016-07-20 16:23:017728TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087729 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7730}
7731
bncd16676a2016-07-20 16:23:017732TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087733 ConnectStatusHelper(
7734 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7735}
7736
bncd16676a2016-07-20 16:23:017737TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087738 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7739}
7740
bncd16676a2016-07-20 16:23:017741TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087742 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7743}
7744
bncd16676a2016-07-20 16:23:017745TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087746 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7747}
7748
bncd16676a2016-07-20 16:23:017749TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087750 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7751}
7752
bncd16676a2016-07-20 16:23:017753TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087754 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7755}
7756
bncd16676a2016-07-20 16:23:017757TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087758 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7759}
7760
bncd16676a2016-07-20 16:23:017761TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087762 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7763}
7764
[email protected]038e9a32008-10-08 22:40:167765// Test the flow when both the proxy server AND origin server require
7766// authentication. Again, this uses basic auth for both since that is
7767// the simplest to mock.
bncd16676a2016-07-20 16:23:017768TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277769 HttpRequestInfo request;
7770 request.method = "GET";
bncce36dca22015-04-21 22:11:237771 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107772 request.traffic_annotation =
7773 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277774
[email protected]038e9a32008-10-08 22:40:167775 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567776 session_deps_.proxy_resolution_service =
7777 ConfiguredProxyResolutionService::CreateFixed(
7778 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077780
bnc691fda62016-08-12 00:43:167781 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167782
[email protected]f9ee6b52008-11-08 06:46:237783 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237784 MockWrite(
7785 "GET http://www.example.org/ HTTP/1.1\r\n"
7786 "Host: www.example.org\r\n"
7787 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237788 };
7789
[email protected]038e9a32008-10-08 22:40:167790 MockRead data_reads1[] = {
7791 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7792 // Give a couple authenticate options (only the middle one is actually
7793 // supported).
[email protected]22927ad2009-09-21 19:56:197794 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167795 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7796 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7797 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7798 // Large content-length -- won't matter, as connection will be reset.
7799 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067800 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167801 };
7802
bnc691fda62016-08-12 00:43:167803 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167804 // request we should be issuing -- the final header line contains the
7805 // proxy's credentials.
7806 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237807 MockWrite(
7808 "GET http://www.example.org/ HTTP/1.1\r\n"
7809 "Host: www.example.org\r\n"
7810 "Proxy-Connection: keep-alive\r\n"
7811 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167812 };
7813
7814 // Now the proxy server lets the request pass through to origin server.
7815 // The origin server responds with a 401.
7816 MockRead data_reads2[] = {
7817 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7818 // Note: We are using the same realm-name as the proxy server. This is
7819 // completely valid, as realms are unique across hosts.
7820 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7821 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7822 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067823 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167824 };
7825
bnc691fda62016-08-12 00:43:167826 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167827 // the credentials for both the proxy and origin server.
7828 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237829 MockWrite(
7830 "GET http://www.example.org/ HTTP/1.1\r\n"
7831 "Host: www.example.org\r\n"
7832 "Proxy-Connection: keep-alive\r\n"
7833 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7834 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167835 };
7836
7837 // Lastly we get the desired content.
7838 MockRead data_reads3[] = {
7839 MockRead("HTTP/1.0 200 OK\r\n"),
7840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7841 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067842 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167843 };
7844
Ryan Sleevib8d7ea02018-05-07 20:01:017845 StaticSocketDataProvider data1(data_reads1, data_writes1);
7846 StaticSocketDataProvider data2(data_reads2, data_writes2);
7847 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077848 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7849 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7850 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167851
[email protected]49639fa2011-12-20 23:22:417852 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167853
tfarina42834112016-09-22 13:38:207854 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017855 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167856
7857 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017858 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167859
bnc691fda62016-08-12 00:43:167860 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527861 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587862 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167863
[email protected]49639fa2011-12-20 23:22:417864 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167865
bnc691fda62016-08-12 00:43:167866 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017867 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167868
7869 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017870 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167871
bnc691fda62016-08-12 00:43:167872 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527873 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587874 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167875
[email protected]49639fa2011-12-20 23:22:417876 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167877
bnc691fda62016-08-12 00:43:167878 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7879 callback3.callback());
robpercival214763f2016-07-01 23:27:017880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167881
7882 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017883 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167884
bnc691fda62016-08-12 00:43:167885 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587886 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167887 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167888}
[email protected]4ddaf2502008-10-23 18:26:197889
[email protected]ea9dc9a2009-09-05 00:43:327890// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7891// can't hook into its internals to cause it to generate predictable NTLM
7892// authorization headers.
7893#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377894// The NTLM authentication unit tests are based on known test data from the
7895// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7896// flow rather than the implementation of the NTLM protocol. See net/ntlm
7897// for the implementation and testing of the protocol.
7898//
7899// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297900
7901// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557902TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427903 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247904 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557905 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107906 request.traffic_annotation =
7907 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547908
7909 // Ensure load is not disrupted by flags which suppress behaviour specific
7910 // to other auth schemes.
7911 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247912
Asanka Herathbf0b55d2019-12-07 03:27:097913 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:097914 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097915 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277916
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377917 // Generate the NTLM messages based on known test data.
7918 std::string negotiate_msg;
7919 std::string challenge_msg;
7920 std::string authenticate_msg;
7921 base::Base64Encode(
7922 base::StringPiece(
7923 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247924 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377925 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557926 base::Base64Encode(
7927 base::StringPiece(
7928 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247929 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557930 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377931 base::Base64Encode(
7932 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097933 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557934 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247935 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557936 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377937 &authenticate_msg);
7938
[email protected]3f918782009-02-28 01:29:247939 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557940 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7941 "Host: server\r\n"
7942 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247943 };
7944
7945 MockRead data_reads1[] = {
7946 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047947 // Negotiate and NTLM are often requested together. However, we only want
7948 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7949 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247950 MockRead("WWW-Authenticate: NTLM\r\n"),
7951 MockRead("Connection: close\r\n"),
7952 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367953 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247954 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247955 };
7956
7957 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167958 // After restarting with a null identity, this is the
7959 // request we should be issuing -- the final header line contains a Type
7960 // 1 message.
7961 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557962 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167963 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377964 "Authorization: NTLM "),
7965 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247966
bnc691fda62016-08-12 00:43:167967 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377968 // (using correct credentials). The second request continues on the
7969 // same connection.
bnc691fda62016-08-12 00:43:167970 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557971 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167972 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377973 "Authorization: NTLM "),
7974 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247975 };
7976
7977 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027978 // The origin server responds with a Type 2 message.
7979 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377980 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7981 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027982 MockRead("Content-Type: text/html\r\n\r\n"),
7983 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247984
Bence Béky1e4ef192017-09-18 19:58:027985 // Lastly we get the desired content.
7986 MockRead("HTTP/1.1 200 OK\r\n"),
7987 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7988 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247989 };
7990
Ryan Sleevib8d7ea02018-05-07 20:01:017991 StaticSocketDataProvider data1(data_reads1, data_writes1);
7992 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077993 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7994 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247995
Bence Béky83eb3512017-09-05 12:56:097996 SSLSocketDataProvider ssl1(ASYNC, OK);
7997 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7998 SSLSocketDataProvider ssl2(ASYNC, OK);
7999 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8000
[email protected]49639fa2011-12-20 23:22:418001 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:248002
bnc691fda62016-08-12 00:43:168003 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508004
tfarina42834112016-09-22 13:38:208005 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018006 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248007
8008 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018009 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248010
bnc691fda62016-08-12 00:43:168011 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228012
bnc691fda62016-08-12 00:43:168013 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528014 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588015 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:248016
[email protected]49639fa2011-12-20 23:22:418017 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:258018
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378019 rv = trans.RestartWithAuth(
8020 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8021 callback2.callback());
robpercival214763f2016-07-01 23:27:018022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258023
8024 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018025 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258026
bnc691fda62016-08-12 00:43:168027 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258028
bnc691fda62016-08-12 00:43:168029 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528030 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588031 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:258032
[email protected]49639fa2011-12-20 23:22:418033 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:248034
bnc691fda62016-08-12 00:43:168035 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018036 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248037
[email protected]0757e7702009-03-27 04:00:228038 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018039 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248040
bnc691fda62016-08-12 00:43:168041 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528042 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588043 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028044 EXPECT_EQ(14, response->headers->GetContentLength());
8045
8046 std::string response_data;
8047 rv = ReadTransaction(&trans, &response_data);
8048 EXPECT_THAT(rv, IsOk());
8049 EXPECT_EQ("Please Login\r\n", response_data);
8050
8051 EXPECT_TRUE(data1.AllReadDataConsumed());
8052 EXPECT_TRUE(data1.AllWriteDataConsumed());
8053 EXPECT_TRUE(data2.AllReadDataConsumed());
8054 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:248055}
8056
[email protected]385a4672009-03-11 22:21:298057// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558058TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:428059 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:298060 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558061 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:108062 request.traffic_annotation =
8063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:298064
Asanka Herathbf0b55d2019-12-07 03:27:098065 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098066 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278068
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378069 // Generate the NTLM messages based on known test data.
8070 std::string negotiate_msg;
8071 std::string challenge_msg;
8072 std::string authenticate_msg;
8073 base::Base64Encode(
8074 base::StringPiece(
8075 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248076 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378077 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558078 base::Base64Encode(
8079 base::StringPiece(
8080 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248081 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558082 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378083 base::Base64Encode(
8084 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098085 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558086 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248087 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558088 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378089 &authenticate_msg);
8090
8091 // The authenticate message when |kWrongPassword| is sent.
8092 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558093 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
8094 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
8095 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
8096 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
8097 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
8098 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378099
Zentaro Kavanagh1890a3d2018-01-29 19:52:558100 // Sanity check that it's the same length as the correct authenticate message
8101 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378102 ASSERT_EQ(authenticate_msg.length(),
8103 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:558104 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378105
[email protected]385a4672009-03-11 22:21:298106 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558107 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8108 "Host: server\r\n"
8109 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298110 };
8111
8112 MockRead data_reads1[] = {
8113 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048114 // Negotiate and NTLM are often requested together. However, we only want
8115 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8116 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:298117 MockRead("WWW-Authenticate: NTLM\r\n"),
8118 MockRead("Connection: close\r\n"),
8119 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368120 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298121 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298122 };
8123
8124 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168125 // After restarting with a null identity, this is the
8126 // request we should be issuing -- the final header line contains a Type
8127 // 1 message.
8128 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558129 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168130 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378131 "Authorization: NTLM "),
8132 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298133
bnc691fda62016-08-12 00:43:168134 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378135 // (using incorrect credentials). The second request continues on the
8136 // same connection.
bnc691fda62016-08-12 00:43:168137 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558138 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168139 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378140 "Authorization: NTLM "),
8141 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298142 };
8143
8144 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378145 // The origin server responds with a Type 2 message.
8146 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8147 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8148 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8149 MockRead("Content-Type: text/html\r\n\r\n"),
8150 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298151
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378152 // Wrong password.
8153 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8154 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8155 MockRead("Content-Length: 42\r\n"),
8156 MockRead("Content-Type: text/html\r\n\r\n"),
8157 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298158 };
8159
8160 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168161 // After restarting with a null identity, this is the
8162 // request we should be issuing -- the final header line contains a Type
8163 // 1 message.
8164 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558165 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168166 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378167 "Authorization: NTLM "),
8168 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298169
bnc691fda62016-08-12 00:43:168170 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8171 // (the credentials for the origin server). The second request continues
8172 // on the same connection.
8173 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558174 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168175 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378176 "Authorization: NTLM "),
8177 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298178 };
8179
8180 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028181 // The origin server responds with a Type 2 message.
8182 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378183 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8184 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028185 MockRead("Content-Type: text/html\r\n\r\n"),
8186 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298187
Bence Béky1e4ef192017-09-18 19:58:028188 // Lastly we get the desired content.
8189 MockRead("HTTP/1.1 200 OK\r\n"),
8190 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8191 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298192 };
8193
Ryan Sleevib8d7ea02018-05-07 20:01:018194 StaticSocketDataProvider data1(data_reads1, data_writes1);
8195 StaticSocketDataProvider data2(data_reads2, data_writes2);
8196 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8198 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8199 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298200
Bence Béky83eb3512017-09-05 12:56:098201 SSLSocketDataProvider ssl1(ASYNC, OK);
8202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8203 SSLSocketDataProvider ssl2(ASYNC, OK);
8204 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8205 SSLSocketDataProvider ssl3(ASYNC, OK);
8206 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8207
[email protected]49639fa2011-12-20 23:22:418208 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298209
bnc691fda62016-08-12 00:43:168210 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508211
tfarina42834112016-09-22 13:38:208212 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298214
8215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018216 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298217
bnc691fda62016-08-12 00:43:168218 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298219
bnc691fda62016-08-12 00:43:168220 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528221 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588222 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298223
[email protected]49639fa2011-12-20 23:22:418224 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298225
[email protected]0757e7702009-03-27 04:00:228226 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378227 rv = trans.RestartWithAuth(
8228 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8229 callback2.callback());
robpercival214763f2016-07-01 23:27:018230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298231
[email protected]10af5fe72011-01-31 16:17:258232 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018233 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298234
bnc691fda62016-08-12 00:43:168235 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418236 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168237 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018238 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258239 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018240 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168241 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228242
bnc691fda62016-08-12 00:43:168243 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528244 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588245 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228246
[email protected]49639fa2011-12-20 23:22:418247 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228248
8249 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378250 rv = trans.RestartWithAuth(
8251 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8252 callback4.callback());
robpercival214763f2016-07-01 23:27:018253 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258254
8255 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018256 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258257
bnc691fda62016-08-12 00:43:168258 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258259
[email protected]49639fa2011-12-20 23:22:418260 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258261
8262 // One more roundtrip
bnc691fda62016-08-12 00:43:168263 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228265
8266 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018267 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228268
bnc691fda62016-08-12 00:43:168269 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588270 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028271 EXPECT_EQ(14, response->headers->GetContentLength());
8272
8273 std::string response_data;
8274 rv = ReadTransaction(&trans, &response_data);
8275 EXPECT_THAT(rv, IsOk());
8276 EXPECT_EQ("Please Login\r\n", response_data);
8277
8278 EXPECT_TRUE(data1.AllReadDataConsumed());
8279 EXPECT_TRUE(data1.AllWriteDataConsumed());
8280 EXPECT_TRUE(data2.AllReadDataConsumed());
8281 EXPECT_TRUE(data2.AllWriteDataConsumed());
8282 EXPECT_TRUE(data3.AllReadDataConsumed());
8283 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298284}
Bence Béky83eb3512017-09-05 12:56:098285
Bence Béky3238f2e12017-09-22 22:44:498286// Server requests NTLM authentication, which is not supported over HTTP/2.
8287// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098288TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Asanka Herathbf0b55d2019-12-07 03:27:098289 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098290 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098291
Zentaro Kavanagh1890a3d2018-01-29 19:52:558292 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098293
8294 HttpRequestInfo request;
8295 request.method = "GET";
8296 request.url = GURL(kUrl);
Ramin Halavatib5e433e2018-02-07 07:41:108297 request.traffic_annotation =
8298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098299
8300 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:138301 spdy::SpdyHeaderBlock request_headers0(
8302 spdy_util_.ConstructGetHeaderBlock(kUrl));
8303 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098304 1, std::move(request_headers0), LOWEST, true));
8305
Ryan Hamilton0239aac2018-05-19 00:03:138306 spdy::SpdyHeaderBlock response_headers0;
8307 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098308 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138309 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098310 1, std::move(response_headers0), true));
8311
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378312 // Stream 1 is closed.
8313 spdy_util_.UpdateWithStreamDestruction(1);
8314
8315 // Generate the NTLM messages based on known test data.
8316 std::string negotiate_msg;
8317 std::string challenge_msg;
8318 std::string authenticate_msg;
8319 base::Base64Encode(
8320 base::StringPiece(
8321 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248322 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378323 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558324 base::Base64Encode(
8325 base::StringPiece(
8326 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248327 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558328 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378329 base::Base64Encode(
8330 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098331 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558332 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248333 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558334 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378335 &authenticate_msg);
8336
Bence Béky3238f2e12017-09-22 22:44:498337 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168338 MockRead reads0[] = {CreateMockRead(resp, 1),
8339 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098340
8341 // Retry yet again using HTTP/1.1.
8342 MockWrite writes1[] = {
8343 // After restarting with a null identity, this is the
8344 // request we should be issuing -- the final header line contains a Type
8345 // 1 message.
8346 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558347 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098348 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378349 "Authorization: NTLM "),
8350 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098351
8352 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8353 // (the credentials for the origin server). The second request continues
8354 // on the same connection.
8355 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558356 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098357 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378358 "Authorization: NTLM "),
8359 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098360 };
8361
8362 MockRead reads1[] = {
8363 // The origin server responds with a Type 2 message.
8364 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378365 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8366 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098367 MockRead("Content-Type: text/html\r\n\r\n"),
8368 MockRead("You are not authorized to view this page\r\n"),
8369
8370 // Lastly we get the desired content.
8371 MockRead("HTTP/1.1 200 OK\r\n"),
8372 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028373 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098374 };
Ryan Sleevib8d7ea02018-05-07 20:01:018375 SequencedSocketData data0(reads0, writes0);
8376 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098377 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8378 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8379
8380 SSLSocketDataProvider ssl0(ASYNC, OK);
8381 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168382 ssl0.next_protos_expected_in_ssl_config =
8383 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098384 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168385 // When creating the second connection, only HTTP/1.1 should be allowed.
8386 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098387 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8389
8390 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8391 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8392
8393 TestCompletionCallback callback1;
8394 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8396
8397 rv = callback1.WaitForResult();
8398 EXPECT_THAT(rv, IsOk());
8399
8400 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8401
8402 const HttpResponseInfo* response = trans.GetResponseInfo();
8403 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588404 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098405
8406 TestCompletionCallback callback2;
8407
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378408 rv = trans.RestartWithAuth(
8409 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8410 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098411 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8412
8413 rv = callback2.WaitForResult();
8414 EXPECT_THAT(rv, IsOk());
8415
8416 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8417
8418 response = trans.GetResponseInfo();
8419 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588420 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098421
8422 TestCompletionCallback callback3;
8423
8424 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8425 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8426
8427 rv = callback3.WaitForResult();
8428 EXPECT_THAT(rv, IsOk());
8429
8430 response = trans.GetResponseInfo();
8431 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588432 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028433 EXPECT_EQ(14, response->headers->GetContentLength());
8434
8435 std::string response_data;
8436 rv = ReadTransaction(&trans, &response_data);
8437 EXPECT_THAT(rv, IsOk());
8438 EXPECT_EQ("Please Login\r\n", response_data);
8439
8440 EXPECT_TRUE(data0.AllReadDataConsumed());
8441 EXPECT_TRUE(data0.AllWriteDataConsumed());
8442 EXPECT_TRUE(data1.AllReadDataConsumed());
8443 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098444}
David Benjamin5cb91132018-04-06 05:54:498445
Matt Menkef2ee07c2019-08-29 02:10:368446#if BUILDFLAG(ENABLE_WEBSOCKETS)
8447
8448// Variant of above test using WebSockets.
8449TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8450 const GURL kInitialUrl("https://server/");
8451 const GURL kWebSocketUrl("wss://server/");
Asanka Herathbf0b55d2019-12-07 03:27:098452 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Matt Menkef2ee07c2019-08-29 02:10:368453 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8454
8455 // Initial request establishes an H2 connection, which will then be reused for
8456 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8457 // it won't create a new one.
8458 spdy::SpdyHeaderBlock initial_request_headers(
8459 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8460 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8461 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8462 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8463
8464 // Settings frame, indicating WebSockets is supported.
8465 spdy::SettingsMap settings;
8466 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8467 spdy::SpdySerializedFrame settings_frame(
8468 spdy_util_.ConstructSpdySettings(settings));
8469
8470 // Response headers for first request. Body is never received, but that
8471 // shouldn't matter for the purposes of this test.
8472 spdy::SpdySerializedFrame initial_response(
8473 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8474
8475 // First WebSocket request, which has no credentials.
8476 spdy::SpdyHeaderBlock websocket_request_headers;
8477 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8478 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8479 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8480 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8481 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8482 websocket_request_headers["origin"] = "http://server";
8483 websocket_request_headers["sec-websocket-version"] = "13";
8484 websocket_request_headers["sec-websocket-extensions"] =
8485 "permessage-deflate; client_max_window_bits";
8486 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8487 3, std::move(websocket_request_headers), MEDIUM, false));
8488
8489 // Auth challenge to WebSocket request.
8490 spdy::SpdyHeaderBlock auth_challenge_headers;
8491 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8492 auth_challenge_headers["www-authenticate"] = "NTLM";
8493 spdy::SpdySerializedFrame websocket_auth_challenge(
8494 spdy_util_.ConstructSpdyResponseHeaders(
8495 3, std::move(auth_challenge_headers), true));
8496
8497 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8498 CreateMockWrite(settings_ack, 2),
8499 CreateMockWrite(websocket_request, 4),
8500 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8501 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8502 CreateMockRead(initial_response, 3),
8503 CreateMockRead(websocket_auth_challenge, 5),
8504 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8505
8506 // Generate the NTLM messages based on known test data.
8507 std::string negotiate_msg;
8508 std::string challenge_msg;
8509 std::string authenticate_msg;
8510 base::Base64Encode(
8511 base::StringPiece(
8512 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8513 base::size(ntlm::test::kExpectedNegotiateMsg)),
8514 &negotiate_msg);
8515 base::Base64Encode(
8516 base::StringPiece(
8517 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8518 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8519 &challenge_msg);
8520 base::Base64Encode(
8521 base::StringPiece(
8522 reinterpret_cast<const char*>(
8523 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8524 base::size(
8525 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8526 &authenticate_msg);
8527
8528 // Retry yet again using HTTP/1.1.
8529 MockWrite writes1[] = {
8530 // After restarting with a null identity, this is the
8531 // request we should be issuing -- the final header line contains a Type
8532 // 1 message.
8533 MockWrite("GET / HTTP/1.1\r\n"
8534 "Host: server\r\n"
8535 "Connection: Upgrade\r\n"
8536 "Authorization: NTLM "),
8537 MockWrite(negotiate_msg.c_str()),
8538 MockWrite("\r\n"),
8539 MockWrite("Origin: http://server\r\n"
8540 "Sec-WebSocket-Version: 13\r\n"
8541 "Upgrade: websocket\r\n"
8542 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8543 "Sec-WebSocket-Extensions: permessage-deflate; "
8544 "client_max_window_bits\r\n\r\n"),
8545
8546 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8547 // (the credentials for the origin server). The second request continues
8548 // on the same connection.
8549 MockWrite("GET / HTTP/1.1\r\n"
8550 "Host: server\r\n"
8551 "Connection: Upgrade\r\n"
8552 "Authorization: NTLM "),
8553 MockWrite(authenticate_msg.c_str()),
8554 MockWrite("\r\n"),
8555 MockWrite("Origin: http://server\r\n"
8556 "Sec-WebSocket-Version: 13\r\n"
8557 "Upgrade: websocket\r\n"
8558 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8559 "Sec-WebSocket-Extensions: permessage-deflate; "
8560 "client_max_window_bits\r\n\r\n"),
8561 };
8562
8563 MockRead reads1[] = {
8564 // The origin server responds with a Type 2 message.
8565 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8566 MockRead("WWW-Authenticate: NTLM "),
8567 MockRead(challenge_msg.c_str()),
8568 MockRead("\r\n"),
8569 MockRead("Content-Length: 42\r\n"),
8570 MockRead("Content-Type: text/html\r\n\r\n"),
8571 MockRead("You are not authorized to view this page\r\n"),
8572
8573 // Lastly we get the desired content.
8574 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8575 "Upgrade: websocket\r\n"
8576 "Connection: Upgrade\r\n"
8577 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8578 };
8579 SequencedSocketData data0(reads0, writes0);
8580 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8581 SSLSocketDataProvider ssl0(ASYNC, OK);
8582 ssl0.next_proto = kProtoHTTP2;
8583 ssl0.next_protos_expected_in_ssl_config =
8584 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8585 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8586
8587 StaticSocketDataProvider data1(reads1, writes1);
8588 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8589 SSLSocketDataProvider ssl1(ASYNC, OK);
8590 // When creating the second connection, only HTTP/1.1 should be allowed.
8591 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8592 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8593
8594 session_deps_.enable_websocket_over_http2 = true;
8595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8596
8597 HttpRequestInfo initial_request_info;
8598 initial_request_info.method = "GET";
8599 initial_request_info.url = kInitialUrl;
8600 initial_request_info.traffic_annotation =
8601 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8602 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8603 TestCompletionCallback initial_callback;
8604 int rv = initial_trans.Start(&initial_request_info,
8605 initial_callback.callback(), NetLogWithSource());
8606 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8607
8608 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8609 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8610
8611 HttpRequestInfo websocket_request_info;
8612 websocket_request_info.method = "GET";
8613 websocket_request_info.url = kWebSocketUrl;
8614 websocket_request_info.traffic_annotation =
8615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8616 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8617 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8618 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8619 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8620 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8621 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8622 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8623
8624 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8625
8626 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8627 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8628 &websocket_stream_create_helper);
8629
8630 TestCompletionCallback websocket_callback;
8631 rv = websocket_trans.Start(&websocket_request_info,
8632 websocket_callback.callback(), NetLogWithSource());
8633 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8634
8635 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8636
8637 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8638 ASSERT_TRUE(response);
8639 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8640
8641 rv = websocket_trans.RestartWithAuth(
8642 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8643 websocket_callback.callback());
8644 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8645
8646 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8647
8648 response = websocket_trans.GetResponseInfo();
8649 ASSERT_TRUE(response);
8650 EXPECT_FALSE(response->auth_challenge.has_value());
8651
8652 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8653 websocket_callback.callback());
8654 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8655
8656 // The server should have been marked as requiring HTTP/1.1. The important
8657 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8658 // WSS.
8659 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8660 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8661}
8662
8663#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8664
David Benjamin5cb91132018-04-06 05:54:498665// Test that, if we have an NTLM proxy and the origin resets the connection, we
David Benjamin07a07d652020-02-26 22:26:598666// do no retry forever as a result of TLS retries. This is a regression test for
8667// https://crbug.com/823387. The version interference probe has since been
8668// removed, but we now have a legacy crypto fallback. (If that fallback is
8669// removed, this test should be kept but with the expectations tweaked, in case
8670// future fallbacks are added.)
David Benjamin5cb91132018-04-06 05:54:498671TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8672 // The NTLM test data expects the proxy to be named 'server'. The origin is
8673 // https://origin/.
8674 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:568675 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
David Benjamin5cb91132018-04-06 05:54:498676 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8677
David Benjamin151ec6b2019-08-02 19:38:528678 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498679 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078680 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498681
8682 HttpRequestInfo request;
8683 request.method = "GET";
8684 request.url = GURL("https://origin/");
8685 request.traffic_annotation =
8686 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8687
8688 // Ensure load is not disrupted by flags which suppress behaviour specific
8689 // to other auth schemes.
8690 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8691
Asanka Herathbf0b55d2019-12-07 03:27:098692 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
David Benjamin5cb91132018-04-06 05:54:498693 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8694 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8695
8696 // Generate the NTLM messages based on known test data.
8697 std::string negotiate_msg;
8698 std::string challenge_msg;
8699 std::string authenticate_msg;
8700 base::Base64Encode(
8701 base::StringPiece(
8702 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248703 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498704 &negotiate_msg);
8705 base::Base64Encode(
8706 base::StringPiece(
8707 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248708 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498709 &challenge_msg);
8710 base::Base64Encode(
8711 base::StringPiece(
8712 reinterpret_cast<const char*>(
8713 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248714 base::size(
David Benjamin5cb91132018-04-06 05:54:498715 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8716 &authenticate_msg);
8717
8718 MockWrite data_writes[] = {
8719 // The initial CONNECT request.
8720 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8721 "Host: origin:443\r\n"
8722 "Proxy-Connection: keep-alive\r\n\r\n"),
8723
8724 // After restarting with an identity.
8725 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8726 "Host: origin:443\r\n"
8727 "Proxy-Connection: keep-alive\r\n"
8728 "Proxy-Authorization: NTLM "),
8729 MockWrite(negotiate_msg.c_str()),
8730 // End headers.
8731 MockWrite("\r\n\r\n"),
8732
8733 // The second restart.
8734 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8735 "Host: origin:443\r\n"
8736 "Proxy-Connection: keep-alive\r\n"
8737 "Proxy-Authorization: NTLM "),
8738 MockWrite(authenticate_msg.c_str()),
8739 // End headers.
8740 MockWrite("\r\n\r\n"),
8741 };
8742
8743 MockRead data_reads[] = {
8744 // The initial NTLM response.
8745 MockRead("HTTP/1.1 407 Access Denied\r\n"
8746 "Content-Length: 0\r\n"
8747 "Proxy-Authenticate: NTLM\r\n\r\n"),
8748
8749 // The NTLM challenge message.
8750 MockRead("HTTP/1.1 407 Access Denied\r\n"
8751 "Content-Length: 0\r\n"
8752 "Proxy-Authenticate: NTLM "),
8753 MockRead(challenge_msg.c_str()),
8754 // End headers.
8755 MockRead("\r\n\r\n"),
8756
8757 // Finally the tunnel is established.
8758 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
8759 };
8760
Ryan Sleevib8d7ea02018-05-07 20:01:018761 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:498762 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:498763 session_deps_.socket_factory->AddSocketDataProvider(&data);
8764 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:498765
David Benjamin07a07d652020-02-26 22:26:598766 StaticSocketDataProvider data2(data_reads, data_writes);
8767 SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
8768 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8769 session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);
8770
David Benjamin5cb91132018-04-06 05:54:498771 // Start the transaction. The proxy responds with an NTLM authentication
8772 // request.
8773 TestCompletionCallback callback;
8774 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8775 int rv = callback.GetResult(
8776 trans.Start(&request, callback.callback(), NetLogWithSource()));
8777
8778 EXPECT_THAT(rv, IsOk());
8779 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8780 const HttpResponseInfo* response = trans.GetResponseInfo();
8781 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588782 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:498783
David Benjamind61bd532019-04-23 21:11:378784 // Configure credentials and restart. The proxy responds with the challenge
8785 // message.
David Benjamin5cb91132018-04-06 05:54:498786 rv = callback.GetResult(trans.RestartWithAuth(
8787 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8788 callback.callback()));
8789 EXPECT_THAT(rv, IsOk());
8790 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8791 response = trans.GetResponseInfo();
8792 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588793 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:498794
David Benjamin07a07d652020-02-26 22:26:598795 // Restart once more. The tunnel will be established and the the SSL handshake
8796 // will reset. The fallback will then kick in and restart the process. The
8797 // proxy responds with another NTLM authentiation request, but we don't need
8798 // to provide credentials as the cached ones work.
8799 rv = callback.GetResult(
8800 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8801 EXPECT_THAT(rv, IsOk());
8802 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8803 response = trans.GetResponseInfo();
8804 ASSERT_TRUE(response);
8805 EXPECT_FALSE(response->auth_challenge.has_value());
8806
8807 // The proxy responds with the NTLM challenge message.
8808 rv = callback.GetResult(
8809 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8810 EXPECT_THAT(rv, IsOk());
8811 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8812 response = trans.GetResponseInfo();
8813 ASSERT_TRUE(response);
8814 EXPECT_FALSE(response->auth_challenge.has_value());
8815
8816 // Send the NTLM authenticate message. The tunnel is established and the
8817 // handshake resets again. We should not retry again.
David Benjamin5cb91132018-04-06 05:54:498818 rv = callback.GetResult(
8819 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8820 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
8821}
8822
[email protected]ea9dc9a2009-09-05 00:43:328823#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:298824
[email protected]4ddaf2502008-10-23 18:26:198825// Test reading a server response which has only headers, and no body.
8826// After some maximum number of bytes is consumed, the transaction should
8827// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018828TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428829 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198830 request.method = "GET";
bncce36dca22015-04-21 22:11:238831 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108832 request.traffic_annotation =
8833 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198834
danakj1fd259a02016-04-16 03:17:098835 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168836 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278837
[email protected]b75b7b2f2009-10-06 00:54:538838 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438839 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538840 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198841
8842 MockRead data_reads[] = {
8843 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068844 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198845 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068846 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198847 };
Ryan Sleevib8d7ea02018-05-07 20:01:018848 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078849 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198850
[email protected]49639fa2011-12-20 23:22:418851 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198852
tfarina42834112016-09-22 13:38:208853 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018854 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198855
8856 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018857 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198858}
[email protected]f4e426b2008-11-05 00:24:498859
8860// Make sure that we don't try to reuse a TCPClientSocket when failing to
8861// establish tunnel.
8862// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018863TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278864 HttpRequestInfo request;
8865 request.method = "GET";
bncce36dca22015-04-21 22:11:238866 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108867 request.traffic_annotation =
8868 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278869
[email protected]f4e426b2008-11-05 00:24:498870 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:568871 session_deps_.proxy_resolution_service =
8872 ConfiguredProxyResolutionService::CreateFixed(
8873 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018874
danakj1fd259a02016-04-16 03:17:098875 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498876
bnc87dcefc2017-05-25 12:47:588877 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198878 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498879
[email protected]f4e426b2008-11-05 00:24:498880 // Since we have proxy, should try to establish tunnel.
8881 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178882 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8883 "Host: www.example.org:443\r\n"
8884 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498885 };
8886
[email protected]77848d12008-11-14 00:00:228887 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498888 // connection. Usually a proxy would return 501 (not implemented),
8889 // or 200 (tunnel established).
8890 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238891 MockRead("HTTP/1.1 404 Not Found\r\n"),
8892 MockRead("Content-Length: 10\r\n\r\n"),
8893 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498894 };
8895
Ryan Sleevib8d7ea02018-05-07 20:01:018896 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078897 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498898
[email protected]49639fa2011-12-20 23:22:418899 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498900
tfarina42834112016-09-22 13:38:208901 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018902 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498903
8904 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018905 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498906
[email protected]b4404c02009-04-10 16:38:528907 // Empty the current queue. This is necessary because idle sockets are
8908 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558909 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528910
[email protected]f4e426b2008-11-05 00:24:498911 // We now check to make sure the TCPClientSocket was not added back to
8912 // the pool.
[email protected]90499482013-06-01 00:39:508913 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498914 trans.reset();
fdoray92e35a72016-06-10 15:54:558915 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498916 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508917 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498918}
[email protected]372d34a2008-11-05 21:30:518919
[email protected]1b157c02009-04-21 01:55:408920// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018921TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428922 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408923 request.method = "GET";
bncce36dca22015-04-21 22:11:238924 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108925 request.traffic_annotation =
8926 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408927
danakj1fd259a02016-04-16 03:17:098928 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278929
bnc691fda62016-08-12 00:43:168930 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278931
[email protected]1b157c02009-04-21 01:55:408932 MockRead data_reads[] = {
8933 // A part of the response body is received with the response headers.
8934 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8935 // The rest of the response body is received in two parts.
8936 MockRead("lo"),
8937 MockRead(" world"),
8938 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068939 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408940 };
8941
Ryan Sleevib8d7ea02018-05-07 20:01:018942 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078943 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408944
[email protected]49639fa2011-12-20 23:22:418945 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408946
tfarina42834112016-09-22 13:38:208947 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408949
8950 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018951 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408952
bnc691fda62016-08-12 00:43:168953 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528954 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408955
wezca1070932016-05-26 20:30:528956 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408957 std::string status_line = response->headers->GetStatusLine();
8958 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8959
[email protected]90499482013-06-01 00:39:508960 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408961
8962 std::string response_data;
bnc691fda62016-08-12 00:43:168963 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018964 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408965 EXPECT_EQ("hello world", response_data);
8966
8967 // Empty the current queue. This is necessary because idle sockets are
8968 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558969 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408970
8971 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508972 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408973}
8974
[email protected]76a505b2010-08-25 06:23:008975// Make sure that we recycle a SSL socket after reading all of the response
8976// body.
bncd16676a2016-07-20 16:23:018977TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008978 HttpRequestInfo request;
8979 request.method = "GET";
bncce36dca22015-04-21 22:11:238980 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108981 request.traffic_annotation =
8982 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008983
8984 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238985 MockWrite(
8986 "GET / HTTP/1.1\r\n"
8987 "Host: www.example.org\r\n"
8988 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008989 };
8990
8991 MockRead data_reads[] = {
8992 MockRead("HTTP/1.1 200 OK\r\n"),
8993 MockRead("Content-Length: 11\r\n\r\n"),
8994 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068995 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008996 };
8997
[email protected]8ddf8322012-02-23 18:08:068998 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078999 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:009000
Ryan Sleevib8d7ea02018-05-07 20:01:019001 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079002 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:009003
[email protected]49639fa2011-12-20 23:22:419004 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009005
danakj1fd259a02016-04-16 03:17:099006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169007 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009008
tfarina42834112016-09-22 13:38:209009 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009010
robpercival214763f2016-07-01 23:27:019011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9012 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009013
bnc691fda62016-08-12 00:43:169014 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529015 ASSERT_TRUE(response);
9016 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009017 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9018
[email protected]90499482013-06-01 00:39:509019 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009020
9021 std::string response_data;
bnc691fda62016-08-12 00:43:169022 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019023 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009024 EXPECT_EQ("hello world", response_data);
9025
9026 // Empty the current queue. This is necessary because idle sockets are
9027 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559028 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009029
9030 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239031 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009032}
9033
9034// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
9035// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:019036TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:009037 HttpRequestInfo request;
9038 request.method = "GET";
bncce36dca22015-04-21 22:11:239039 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109040 request.traffic_annotation =
9041 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:009042
9043 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239044 MockWrite(
9045 "GET / HTTP/1.1\r\n"
9046 "Host: www.example.org\r\n"
9047 "Connection: keep-alive\r\n\r\n"),
9048 MockWrite(
9049 "GET / HTTP/1.1\r\n"
9050 "Host: www.example.org\r\n"
9051 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009052 };
9053
9054 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:429055 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9056 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:009057
[email protected]8ddf8322012-02-23 18:08:069058 SSLSocketDataProvider ssl(ASYNC, OK);
9059 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9061 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:009062
Ryan Sleevib8d7ea02018-05-07 20:01:019063 StaticSocketDataProvider data(data_reads, data_writes);
9064 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079065 session_deps_.socket_factory->AddSocketDataProvider(&data);
9066 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:009067
[email protected]49639fa2011-12-20 23:22:419068 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009069
danakj1fd259a02016-04-16 03:17:099070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:589071 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199072 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009073
tfarina42834112016-09-22 13:38:209074 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009075
robpercival214763f2016-07-01 23:27:019076 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9077 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009078
9079 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529080 ASSERT_TRUE(response);
9081 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009082 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9083
[email protected]90499482013-06-01 00:39:509084 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009085
9086 std::string response_data;
9087 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019088 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009089 EXPECT_EQ("hello world", response_data);
9090
9091 // Empty the current queue. This is necessary because idle sockets are
9092 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559093 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009094
9095 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239096 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009097
9098 // Now start the second transaction, which should reuse the previous socket.
9099
bnc87dcefc2017-05-25 12:47:589100 trans =
Jeremy Roman0579ed62017-08-29 15:56:199101 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009102
tfarina42834112016-09-22 13:38:209103 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009104
robpercival214763f2016-07-01 23:27:019105 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9106 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009107
9108 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529109 ASSERT_TRUE(response);
9110 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009111 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9112
[email protected]90499482013-06-01 00:39:509113 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009114
9115 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019116 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009117 EXPECT_EQ("hello world", response_data);
9118
9119 // Empty the current queue. This is necessary because idle sockets are
9120 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559121 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009122
9123 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239124 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009125}
9126
maksim.sisov0adf8592016-07-15 06:25:569127// Grab a socket, use it, and put it back into the pool. Then, make
9128// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019129TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569130 HttpRequestInfo request;
9131 request.method = "GET";
9132 request.url = GURL("http://www.example.org/");
9133 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109134 request.traffic_annotation =
9135 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569136
9137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9138
bnc691fda62016-08-12 00:43:169139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569140
9141 MockRead data_reads[] = {
9142 // A part of the response body is received with the response headers.
9143 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9144 // The rest of the response body is received in two parts.
9145 MockRead("lo"), MockRead(" world"),
9146 MockRead("junk"), // Should not be read!!
9147 MockRead(SYNCHRONOUS, OK),
9148 };
9149
Ryan Sleevib8d7ea02018-05-07 20:01:019150 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569151 session_deps_.socket_factory->AddSocketDataProvider(&data);
9152
9153 TestCompletionCallback callback;
9154
tfarina42834112016-09-22 13:38:209155 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9157
9158 EXPECT_THAT(callback.GetResult(rv), IsOk());
9159
bnc691fda62016-08-12 00:43:169160 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569161 ASSERT_TRUE(response);
9162 EXPECT_TRUE(response->headers);
9163 std::string status_line = response->headers->GetStatusLine();
9164 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9165
9166 // Make memory critical notification and ensure the transaction still has been
9167 // operating right.
9168 base::MemoryPressureListener::NotifyMemoryPressure(
9169 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9170 base::RunLoop().RunUntilIdle();
9171
9172 // Socket should not be flushed as long as it is not idle.
9173 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9174
9175 std::string response_data;
bnc691fda62016-08-12 00:43:169176 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569177 EXPECT_THAT(rv, IsOk());
9178 EXPECT_EQ("hello world", response_data);
9179
9180 // Empty the current queue. This is necessary because idle sockets are
9181 // added to the connection pool asynchronously with a PostTask.
9182 base::RunLoop().RunUntilIdle();
9183
9184 // We now check to make sure the socket was added back to the pool.
9185 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9186
9187 // Idle sockets should be flushed now.
9188 base::MemoryPressureListener::NotifyMemoryPressure(
9189 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9190 base::RunLoop().RunUntilIdle();
9191
9192 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9193}
9194
yucliu48f235d2018-01-11 00:59:559195// Disable idle socket closing on memory pressure.
9196// Grab a socket, use it, and put it back into the pool. Then, make
9197// low memory notification and ensure the socket pool is NOT flushed.
9198TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9199 HttpRequestInfo request;
9200 request.method = "GET";
9201 request.url = GURL("http://www.example.org/");
9202 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109203 request.traffic_annotation =
9204 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559205
9206 // Disable idle socket closing on memory pressure.
9207 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9208 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9209
9210 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9211
9212 MockRead data_reads[] = {
9213 // A part of the response body is received with the response headers.
9214 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9215 // The rest of the response body is received in two parts.
9216 MockRead("lo"), MockRead(" world"),
9217 MockRead("junk"), // Should not be read!!
9218 MockRead(SYNCHRONOUS, OK),
9219 };
9220
Ryan Sleevib8d7ea02018-05-07 20:01:019221 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559222 session_deps_.socket_factory->AddSocketDataProvider(&data);
9223
9224 TestCompletionCallback callback;
9225
9226 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9227 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9228
9229 EXPECT_THAT(callback.GetResult(rv), IsOk());
9230
9231 const HttpResponseInfo* response = trans.GetResponseInfo();
9232 ASSERT_TRUE(response);
9233 EXPECT_TRUE(response->headers);
9234 std::string status_line = response->headers->GetStatusLine();
9235 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9236
9237 // Make memory critical notification and ensure the transaction still has been
9238 // operating right.
9239 base::MemoryPressureListener::NotifyMemoryPressure(
9240 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9241 base::RunLoop().RunUntilIdle();
9242
9243 // Socket should not be flushed as long as it is not idle.
9244 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9245
9246 std::string response_data;
9247 rv = ReadTransaction(&trans, &response_data);
9248 EXPECT_THAT(rv, IsOk());
9249 EXPECT_EQ("hello world", response_data);
9250
9251 // Empty the current queue. This is necessary because idle sockets are
9252 // added to the connection pool asynchronously with a PostTask.
9253 base::RunLoop().RunUntilIdle();
9254
9255 // We now check to make sure the socket was added back to the pool.
9256 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9257
9258 // Idle sockets should NOT be flushed on moderate memory pressure.
9259 base::MemoryPressureListener::NotifyMemoryPressure(
9260 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9261 base::RunLoop().RunUntilIdle();
9262
9263 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9264
9265 // Idle sockets should NOT be flushed on critical memory pressure.
9266 base::MemoryPressureListener::NotifyMemoryPressure(
9267 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9268 base::RunLoop().RunUntilIdle();
9269
9270 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9271}
9272
maksim.sisov0adf8592016-07-15 06:25:569273// Grab an SSL socket, use it, and put it back into the pool. Then, make
9274// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019275TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569276 HttpRequestInfo request;
9277 request.method = "GET";
9278 request.url = GURL("https://www.example.org/");
9279 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109280 request.traffic_annotation =
9281 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569282
9283 MockWrite data_writes[] = {
9284 MockWrite("GET / HTTP/1.1\r\n"
9285 "Host: www.example.org\r\n"
9286 "Connection: keep-alive\r\n\r\n"),
9287 };
9288
9289 MockRead data_reads[] = {
9290 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9291 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9292
9293 SSLSocketDataProvider ssl(ASYNC, OK);
9294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9295
Ryan Sleevib8d7ea02018-05-07 20:01:019296 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569297 session_deps_.socket_factory->AddSocketDataProvider(&data);
9298
9299 TestCompletionCallback callback;
9300
9301 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169302 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569303
Matt Menke9d5e2c92019-02-05 01:42:239304 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209305 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569306
9307 EXPECT_THAT(callback.GetResult(rv), IsOk());
9308
bnc691fda62016-08-12 00:43:169309 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569310 ASSERT_TRUE(response);
9311 ASSERT_TRUE(response->headers);
9312 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9313
9314 // Make memory critical notification and ensure the transaction still has been
9315 // operating right.
9316 base::MemoryPressureListener::NotifyMemoryPressure(
9317 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9318 base::RunLoop().RunUntilIdle();
9319
Matt Menke9d5e2c92019-02-05 01:42:239320 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569321
9322 std::string response_data;
bnc691fda62016-08-12 00:43:169323 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569324 EXPECT_THAT(rv, IsOk());
9325 EXPECT_EQ("hello world", response_data);
9326
9327 // Empty the current queue. This is necessary because idle sockets are
9328 // added to the connection pool asynchronously with a PostTask.
9329 base::RunLoop().RunUntilIdle();
9330
9331 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239332 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569333
9334 // Make memory notification once again and ensure idle socket is closed.
9335 base::MemoryPressureListener::NotifyMemoryPressure(
9336 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9337 base::RunLoop().RunUntilIdle();
9338
Matt Menke9d5e2c92019-02-05 01:42:239339 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569340}
9341
[email protected]b4404c02009-04-10 16:38:529342// Make sure that we recycle a socket after a zero-length response.
9343// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019344TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429345 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529346 request.method = "GET";
bncce36dca22015-04-21 22:11:239347 request.url = GURL(
9348 "http://www.example.org/csi?v=3&s=web&action=&"
9349 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9350 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9351 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:109352 request.traffic_annotation =
9353 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529354
danakj1fd259a02016-04-16 03:17:099355 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279356
[email protected]b4404c02009-04-10 16:38:529357 MockRead data_reads[] = {
9358 MockRead("HTTP/1.1 204 No Content\r\n"
9359 "Content-Length: 0\r\n"
9360 "Content-Type: text/html\r\n\r\n"),
9361 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069362 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529363 };
9364
Ryan Sleevib8d7ea02018-05-07 20:01:019365 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079366 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529367
mmenkecc2298e2015-12-07 18:20:189368 // Transaction must be created after the MockReads, so it's destroyed before
9369 // them.
bnc691fda62016-08-12 00:43:169370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189371
[email protected]49639fa2011-12-20 23:22:419372 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529373
tfarina42834112016-09-22 13:38:209374 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019375 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529376
9377 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019378 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529379
bnc691fda62016-08-12 00:43:169380 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529381 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529382
wezca1070932016-05-26 20:30:529383 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529384 std::string status_line = response->headers->GetStatusLine();
9385 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9386
[email protected]90499482013-06-01 00:39:509387 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529388
9389 std::string response_data;
bnc691fda62016-08-12 00:43:169390 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019391 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529392 EXPECT_EQ("", response_data);
9393
9394 // Empty the current queue. This is necessary because idle sockets are
9395 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559396 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529397
9398 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509399 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529400}
9401
bncd16676a2016-07-20 16:23:019402TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099403 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229404 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199405 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229406 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279407
[email protected]1c773ea12009-04-28 19:58:429408 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519409 // Transaction 1: a GET request that succeeds. The socket is recycled
9410 // after use.
9411 request[0].method = "GET";
9412 request[0].url = GURL("http://www.google.com/");
9413 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109414 request[0].traffic_annotation =
9415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519416 // Transaction 2: a POST request. Reuses the socket kept alive from
9417 // transaction 1. The first attempts fails when writing the POST data.
9418 // This causes the transaction to retry with a new socket. The second
9419 // attempt succeeds.
9420 request[1].method = "POST";
9421 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279422 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519423 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109424 request[1].traffic_annotation =
9425 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519426
danakj1fd259a02016-04-16 03:17:099427 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519428
9429 // The first socket is used for transaction 1 and the first attempt of
9430 // transaction 2.
9431
9432 // The response of transaction 1.
9433 MockRead data_reads1[] = {
9434 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9435 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069436 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519437 };
9438 // The mock write results of transaction 1 and the first attempt of
9439 // transaction 2.
9440 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069441 MockWrite(SYNCHRONOUS, 64), // GET
9442 MockWrite(SYNCHRONOUS, 93), // POST
9443 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519444 };
Ryan Sleevib8d7ea02018-05-07 20:01:019445 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519446
9447 // The second socket is used for the second attempt of transaction 2.
9448
9449 // The response of transaction 2.
9450 MockRead data_reads2[] = {
9451 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9452 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069453 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519454 };
9455 // The mock write results of the second attempt of transaction 2.
9456 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069457 MockWrite(SYNCHRONOUS, 93), // POST
9458 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519459 };
Ryan Sleevib8d7ea02018-05-07 20:01:019460 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519461
[email protected]bb88e1d32013-05-03 23:11:079462 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9463 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519464
thestig9d3bb0c2015-01-24 00:49:519465 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519466 "hello world", "welcome"
9467 };
9468
9469 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169470 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519471
[email protected]49639fa2011-12-20 23:22:419472 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519473
tfarina42834112016-09-22 13:38:209474 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019475 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519476
9477 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019478 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519479
bnc691fda62016-08-12 00:43:169480 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529481 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519482
wezca1070932016-05-26 20:30:529483 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519484 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9485
9486 std::string response_data;
bnc691fda62016-08-12 00:43:169487 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019488 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519489 EXPECT_EQ(kExpectedResponseData[i], response_data);
9490 }
9491}
[email protected]f9ee6b52008-11-08 06:46:239492
9493// Test the request-challenge-retry sequence for basic auth when there is
9494// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169495// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019496TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429497 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239498 request.method = "GET";
bncce36dca22015-04-21 22:11:239499 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419500 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109501 request.traffic_annotation =
9502 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299503
danakj1fd259a02016-04-16 03:17:099504 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169505 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279506
[email protected]a97cca42009-08-14 01:00:299507 // The password contains an escaped character -- for this test to pass it
9508 // will need to be unescaped by HttpNetworkTransaction.
9509 EXPECT_EQ("b%40r", request.url.password());
9510
[email protected]f9ee6b52008-11-08 06:46:239511 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239512 MockWrite(
9513 "GET / HTTP/1.1\r\n"
9514 "Host: www.example.org\r\n"
9515 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239516 };
9517
9518 MockRead data_reads1[] = {
9519 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9520 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9521 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069522 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239523 };
9524
[email protected]2262e3a2012-05-22 16:08:169525 // After the challenge above, the transaction will be restarted using the
9526 // identity from the url (foo, b@r) to answer the challenge.
9527 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239528 MockWrite(
9529 "GET / HTTP/1.1\r\n"
9530 "Host: www.example.org\r\n"
9531 "Connection: keep-alive\r\n"
9532 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169533 };
9534
9535 MockRead data_reads2[] = {
9536 MockRead("HTTP/1.0 200 OK\r\n"),
9537 MockRead("Content-Length: 100\r\n\r\n"),
9538 MockRead(SYNCHRONOUS, OK),
9539 };
9540
Ryan Sleevib8d7ea02018-05-07 20:01:019541 StaticSocketDataProvider data1(data_reads1, data_writes1);
9542 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079543 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9544 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239545
[email protected]49639fa2011-12-20 23:22:419546 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209547 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019548 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239549 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019550 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169551 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169552
9553 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169554 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019555 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169556 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019557 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169558 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229559
bnc691fda62016-08-12 00:43:169560 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529561 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169562
9563 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589564 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169565
9566 EXPECT_EQ(100, response->headers->GetContentLength());
9567
9568 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559569 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169570}
9571
9572// Test the request-challenge-retry sequence for basic auth when there is an
9573// incorrect identity in the URL. The identity from the URL should be used only
9574// once.
bncd16676a2016-07-20 16:23:019575TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169576 HttpRequestInfo request;
9577 request.method = "GET";
9578 // Note: the URL has a username:password in it. The password "baz" is
9579 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239580 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169581
9582 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109583 request.traffic_annotation =
9584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169585
danakj1fd259a02016-04-16 03:17:099586 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169587 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169588
9589 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239590 MockWrite(
9591 "GET / HTTP/1.1\r\n"
9592 "Host: www.example.org\r\n"
9593 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169594 };
9595
9596 MockRead data_reads1[] = {
9597 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9598 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9599 MockRead("Content-Length: 10\r\n\r\n"),
9600 MockRead(SYNCHRONOUS, ERR_FAILED),
9601 };
9602
9603 // After the challenge above, the transaction will be restarted using the
9604 // identity from the url (foo, baz) to answer the challenge.
9605 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239606 MockWrite(
9607 "GET / HTTP/1.1\r\n"
9608 "Host: www.example.org\r\n"
9609 "Connection: keep-alive\r\n"
9610 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169611 };
9612
9613 MockRead data_reads2[] = {
9614 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9615 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9616 MockRead("Content-Length: 10\r\n\r\n"),
9617 MockRead(SYNCHRONOUS, ERR_FAILED),
9618 };
9619
9620 // After the challenge above, the transaction will be restarted using the
9621 // identity supplied by the user (foo, bar) to answer the challenge.
9622 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239623 MockWrite(
9624 "GET / HTTP/1.1\r\n"
9625 "Host: www.example.org\r\n"
9626 "Connection: keep-alive\r\n"
9627 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169628 };
9629
9630 MockRead data_reads3[] = {
9631 MockRead("HTTP/1.0 200 OK\r\n"),
9632 MockRead("Content-Length: 100\r\n\r\n"),
9633 MockRead(SYNCHRONOUS, OK),
9634 };
9635
Ryan Sleevib8d7ea02018-05-07 20:01:019636 StaticSocketDataProvider data1(data_reads1, data_writes1);
9637 StaticSocketDataProvider data2(data_reads2, data_writes2);
9638 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079639 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9640 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9641 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169642
9643 TestCompletionCallback callback1;
9644
tfarina42834112016-09-22 13:38:209645 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019646 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169647
9648 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019649 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169650
bnc691fda62016-08-12 00:43:169651 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169652 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169653 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019654 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169655 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019656 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169657 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169658
bnc691fda62016-08-12 00:43:169659 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529660 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589661 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169662
9663 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169664 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019665 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169666 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019667 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169668 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169669
bnc691fda62016-08-12 00:43:169670 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529671 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169672
9673 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589674 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169675
9676 EXPECT_EQ(100, response->headers->GetContentLength());
9677
[email protected]ea9dc9a2009-09-05 00:43:329678 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559679 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329680}
9681
[email protected]2217aa22013-10-11 03:03:549682
9683// Test the request-challenge-retry sequence for basic auth when there is a
9684// correct identity in the URL, but its use is being suppressed. The identity
9685// from the URL should never be used.
bncd16676a2016-07-20 16:23:019686TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549687 HttpRequestInfo request;
9688 request.method = "GET";
bncce36dca22015-04-21 22:11:239689 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549690 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:109691 request.traffic_annotation =
9692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549693
danakj1fd259a02016-04-16 03:17:099694 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169695 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549696
9697 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239698 MockWrite(
9699 "GET / HTTP/1.1\r\n"
9700 "Host: www.example.org\r\n"
9701 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549702 };
9703
9704 MockRead data_reads1[] = {
9705 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9706 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9707 MockRead("Content-Length: 10\r\n\r\n"),
9708 MockRead(SYNCHRONOUS, ERR_FAILED),
9709 };
9710
9711 // After the challenge above, the transaction will be restarted using the
9712 // identity supplied by the user, not the one in the URL, to answer the
9713 // challenge.
9714 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239715 MockWrite(
9716 "GET / HTTP/1.1\r\n"
9717 "Host: www.example.org\r\n"
9718 "Connection: keep-alive\r\n"
9719 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549720 };
9721
9722 MockRead data_reads3[] = {
9723 MockRead("HTTP/1.0 200 OK\r\n"),
9724 MockRead("Content-Length: 100\r\n\r\n"),
9725 MockRead(SYNCHRONOUS, OK),
9726 };
9727
Ryan Sleevib8d7ea02018-05-07 20:01:019728 StaticSocketDataProvider data1(data_reads1, data_writes1);
9729 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549730 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9731 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9732
9733 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209734 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019735 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549736 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019737 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169738 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549739
bnc691fda62016-08-12 00:43:169740 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529741 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589742 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:549743
9744 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169745 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019746 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549747 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019748 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169749 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549750
bnc691fda62016-08-12 00:43:169751 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529752 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:549753
9754 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589755 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:549756 EXPECT_EQ(100, response->headers->GetContentLength());
9757
9758 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559759 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:549760}
9761
[email protected]f9ee6b52008-11-08 06:46:239762// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:019763TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:099764 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:239765
9766 // Transaction 1: authenticate (foo, bar) on MyRealm1
9767 {
[email protected]1c773ea12009-04-28 19:58:429768 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239769 request.method = "GET";
bncce36dca22015-04-21 22:11:239770 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:109771 request.traffic_annotation =
9772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239773
bnc691fda62016-08-12 00:43:169774 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279775
[email protected]f9ee6b52008-11-08 06:46:239776 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239777 MockWrite(
9778 "GET /x/y/z HTTP/1.1\r\n"
9779 "Host: www.example.org\r\n"
9780 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239781 };
9782
9783 MockRead data_reads1[] = {
9784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9785 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9786 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069787 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239788 };
9789
9790 // Resend with authorization (username=foo, password=bar)
9791 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239792 MockWrite(
9793 "GET /x/y/z HTTP/1.1\r\n"
9794 "Host: www.example.org\r\n"
9795 "Connection: keep-alive\r\n"
9796 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239797 };
9798
9799 // Sever accepts the authorization.
9800 MockRead data_reads2[] = {
9801 MockRead("HTTP/1.0 200 OK\r\n"),
9802 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069803 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239804 };
9805
Ryan Sleevib8d7ea02018-05-07 20:01:019806 StaticSocketDataProvider data1(data_reads1, data_writes1);
9807 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079808 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9809 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239810
[email protected]49639fa2011-12-20 23:22:419811 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239812
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
9816 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019817 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239818
bnc691fda62016-08-12 00:43:169819 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529820 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589821 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239822
[email protected]49639fa2011-12-20 23:22:419823 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239824
bnc691fda62016-08-12 00:43:169825 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9826 callback2.callback());
robpercival214763f2016-07-01 23:27:019827 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239828
9829 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019830 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239831
bnc691fda62016-08-12 00:43:169832 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529833 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589834 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239835 EXPECT_EQ(100, response->headers->GetContentLength());
9836 }
9837
9838 // ------------------------------------------------------------------------
9839
9840 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9841 {
[email protected]1c773ea12009-04-28 19:58:429842 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239843 request.method = "GET";
9844 // Note that Transaction 1 was at /x/y/z, so this is in the same
9845 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239846 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:109847 request.traffic_annotation =
9848 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239849
bnc691fda62016-08-12 00:43:169850 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279851
[email protected]f9ee6b52008-11-08 06:46:239852 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239853 MockWrite(
9854 "GET /x/y/a/b HTTP/1.1\r\n"
9855 "Host: www.example.org\r\n"
9856 "Connection: keep-alive\r\n"
9857 // Send preemptive authorization for MyRealm1
9858 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239859 };
9860
9861 // The server didn't like the preemptive authorization, and
9862 // challenges us for a different realm (MyRealm2).
9863 MockRead data_reads1[] = {
9864 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9865 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9866 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069867 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239868 };
9869
9870 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9871 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239872 MockWrite(
9873 "GET /x/y/a/b HTTP/1.1\r\n"
9874 "Host: www.example.org\r\n"
9875 "Connection: keep-alive\r\n"
9876 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239877 };
9878
9879 // Sever accepts the authorization.
9880 MockRead data_reads2[] = {
9881 MockRead("HTTP/1.0 200 OK\r\n"),
9882 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069883 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239884 };
9885
Ryan Sleevib8d7ea02018-05-07 20:01:019886 StaticSocketDataProvider data1(data_reads1, data_writes1);
9887 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079888 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9889 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239890
[email protected]49639fa2011-12-20 23:22:419891 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239892
tfarina42834112016-09-22 13:38:209893 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019894 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239895
9896 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019897 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239898
bnc691fda62016-08-12 00:43:169899 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529900 ASSERT_TRUE(response);
9901 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049902 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439903 EXPECT_EQ("http://www.example.org",
9904 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049905 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199906 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239907
[email protected]49639fa2011-12-20 23:22:419908 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239909
bnc691fda62016-08-12 00:43:169910 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9911 callback2.callback());
robpercival214763f2016-07-01 23:27:019912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239913
9914 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019915 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239916
bnc691fda62016-08-12 00:43:169917 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529918 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589919 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239920 EXPECT_EQ(100, response->headers->GetContentLength());
9921 }
9922
9923 // ------------------------------------------------------------------------
9924
9925 // Transaction 3: Resend a request in MyRealm's protection space --
9926 // succeed with preemptive authorization.
9927 {
[email protected]1c773ea12009-04-28 19:58:429928 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239929 request.method = "GET";
bncce36dca22015-04-21 22:11:239930 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:109931 request.traffic_annotation =
9932 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239933
bnc691fda62016-08-12 00:43:169934 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279935
[email protected]f9ee6b52008-11-08 06:46:239936 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239937 MockWrite(
9938 "GET /x/y/z2 HTTP/1.1\r\n"
9939 "Host: www.example.org\r\n"
9940 "Connection: keep-alive\r\n"
9941 // The authorization for MyRealm1 gets sent preemptively
9942 // (since the url is in the same protection space)
9943 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239944 };
9945
9946 // Sever accepts the preemptive authorization
9947 MockRead data_reads1[] = {
9948 MockRead("HTTP/1.0 200 OK\r\n"),
9949 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069950 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239951 };
9952
Ryan Sleevib8d7ea02018-05-07 20:01:019953 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079954 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239955
[email protected]49639fa2011-12-20 23:22:419956 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239957
tfarina42834112016-09-22 13:38:209958 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239960
9961 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019962 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239963
bnc691fda62016-08-12 00:43:169964 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529965 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239966
Emily Starkf2c9bbd2019-04-09 17:08:589967 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239968 EXPECT_EQ(100, response->headers->GetContentLength());
9969 }
9970
9971 // ------------------------------------------------------------------------
9972
9973 // Transaction 4: request another URL in MyRealm (however the
9974 // url is not known to belong to the protection space, so no pre-auth).
9975 {
[email protected]1c773ea12009-04-28 19:58:429976 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239977 request.method = "GET";
bncce36dca22015-04-21 22:11:239978 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:109979 request.traffic_annotation =
9980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239981
bnc691fda62016-08-12 00:43:169982 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279983
[email protected]f9ee6b52008-11-08 06:46:239984 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239985 MockWrite(
9986 "GET /x/1 HTTP/1.1\r\n"
9987 "Host: www.example.org\r\n"
9988 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239989 };
9990
9991 MockRead data_reads1[] = {
9992 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9993 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9994 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069995 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239996 };
9997
9998 // Resend with authorization from MyRealm's cache.
9999 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310000 MockWrite(
10001 "GET /x/1 HTTP/1.1\r\n"
10002 "Host: www.example.org\r\n"
10003 "Connection: keep-alive\r\n"
10004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310005 };
10006
10007 // Sever accepts the authorization.
10008 MockRead data_reads2[] = {
10009 MockRead("HTTP/1.0 200 OK\r\n"),
10010 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610011 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310012 };
10013
Ryan Sleevib8d7ea02018-05-07 20:01:0110014 StaticSocketDataProvider data1(data_reads1, data_writes1);
10015 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710016 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10017 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310018
[email protected]49639fa2011-12-20 23:22:4110019 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310020
tfarina42834112016-09-22 13:38:2010021 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310023
10024 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110025 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310026
bnc691fda62016-08-12 00:43:1610027 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110028 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610029 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110030 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210031 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110032 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610033 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210034
bnc691fda62016-08-12 00:43:1610035 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210036 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810037 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310038 EXPECT_EQ(100, response->headers->GetContentLength());
10039 }
10040
10041 // ------------------------------------------------------------------------
10042
10043 // Transaction 5: request a URL in MyRealm, but the server rejects the
10044 // cached identity. Should invalidate and re-prompt.
10045 {
[email protected]1c773ea12009-04-28 19:58:4210046 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310047 request.method = "GET";
bncce36dca22015-04-21 22:11:2310048 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:1010049 request.traffic_annotation =
10050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310051
bnc691fda62016-08-12 00:43:1610052 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710053
[email protected]f9ee6b52008-11-08 06:46:2310054 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310055 MockWrite(
10056 "GET /p/q/t HTTP/1.1\r\n"
10057 "Host: www.example.org\r\n"
10058 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310059 };
10060
10061 MockRead data_reads1[] = {
10062 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10063 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10064 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610065 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310066 };
10067
10068 // Resend with authorization from cache for MyRealm.
10069 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310070 MockWrite(
10071 "GET /p/q/t HTTP/1.1\r\n"
10072 "Host: www.example.org\r\n"
10073 "Connection: keep-alive\r\n"
10074 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310075 };
10076
10077 // Sever rejects the authorization.
10078 MockRead data_reads2[] = {
10079 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10080 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10081 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610082 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310083 };
10084
10085 // At this point we should prompt for new credentials for MyRealm.
10086 // Restart with username=foo3, password=foo4.
10087 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310088 MockWrite(
10089 "GET /p/q/t HTTP/1.1\r\n"
10090 "Host: www.example.org\r\n"
10091 "Connection: keep-alive\r\n"
10092 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310093 };
10094
10095 // Sever accepts the authorization.
10096 MockRead data_reads3[] = {
10097 MockRead("HTTP/1.0 200 OK\r\n"),
10098 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610099 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310100 };
10101
Ryan Sleevib8d7ea02018-05-07 20:01:0110102 StaticSocketDataProvider data1(data_reads1, data_writes1);
10103 StaticSocketDataProvider data2(data_reads2, data_writes2);
10104 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710105 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10106 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10107 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:2310108
[email protected]49639fa2011-12-20 23:22:4110109 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310110
tfarina42834112016-09-22 13:38:2010111 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110112 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310113
10114 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110115 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310116
bnc691fda62016-08-12 00:43:1610117 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110118 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610119 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210121 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110122 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610123 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210124
bnc691fda62016-08-12 00:43:1610125 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210126 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810127 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310128
[email protected]49639fa2011-12-20 23:22:4110129 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:2310130
bnc691fda62016-08-12 00:43:1610131 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
10132 callback3.callback());
robpercival214763f2016-07-01 23:27:0110133 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310134
[email protected]0757e7702009-03-27 04:00:2210135 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110136 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310137
bnc691fda62016-08-12 00:43:1610138 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210139 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810140 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310141 EXPECT_EQ(100, response->headers->GetContentLength());
10142 }
10143}
[email protected]89ceba9a2009-03-21 03:46:0610144
[email protected]3c32c5f2010-05-18 15:18:1210145// Tests that nonce count increments when multiple auth attempts
10146// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110147TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410148 HttpAuthHandlerDigest::Factory* digest_factory =
10149 new HttpAuthHandlerDigest::Factory();
10150 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10151 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10152 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710153 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210155
10156 // Transaction 1: authenticate (foo, bar) on MyRealm1
10157 {
[email protected]3c32c5f2010-05-18 15:18:1210158 HttpRequestInfo request;
10159 request.method = "GET";
bncce36dca22015-04-21 22:11:2310160 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010161 request.traffic_annotation =
10162 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210163
bnc691fda62016-08-12 00:43:1610164 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710165
[email protected]3c32c5f2010-05-18 15:18:1210166 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310167 MockWrite(
10168 "GET /x/y/z HTTP/1.1\r\n"
10169 "Host: www.example.org\r\n"
10170 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210171 };
10172
10173 MockRead data_reads1[] = {
10174 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10175 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10176 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610177 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210178 };
10179
10180 // Resend with authorization (username=foo, password=bar)
10181 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310182 MockWrite(
10183 "GET /x/y/z HTTP/1.1\r\n"
10184 "Host: www.example.org\r\n"
10185 "Connection: keep-alive\r\n"
10186 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10187 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10188 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10189 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210190 };
10191
10192 // Sever accepts the authorization.
10193 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810194 MockRead("HTTP/1.0 200 OK\r\n"),
10195 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210196 };
10197
Ryan Sleevib8d7ea02018-05-07 20:01:0110198 StaticSocketDataProvider data1(data_reads1, data_writes1);
10199 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710200 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10201 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210202
[email protected]49639fa2011-12-20 23:22:4110203 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210204
tfarina42834112016-09-22 13:38:2010205 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110206 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210207
10208 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110209 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210210
bnc691fda62016-08-12 00:43:1610211 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210212 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810213 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210214
[email protected]49639fa2011-12-20 23:22:4110215 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210216
bnc691fda62016-08-12 00:43:1610217 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10218 callback2.callback());
robpercival214763f2016-07-01 23:27:0110219 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210220
10221 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110222 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210223
bnc691fda62016-08-12 00:43:1610224 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210225 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810226 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210227 }
10228
10229 // ------------------------------------------------------------------------
10230
10231 // Transaction 2: Request another resource in digestive's protection space.
10232 // This will preemptively add an Authorization header which should have an
10233 // "nc" value of 2 (as compared to 1 in the first use.
10234 {
[email protected]3c32c5f2010-05-18 15:18:1210235 HttpRequestInfo request;
10236 request.method = "GET";
10237 // Note that Transaction 1 was at /x/y/z, so this is in the same
10238 // protection space as digest.
bncce36dca22015-04-21 22:11:2310239 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010240 request.traffic_annotation =
10241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210242
bnc691fda62016-08-12 00:43:1610243 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710244
[email protected]3c32c5f2010-05-18 15:18:1210245 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310246 MockWrite(
10247 "GET /x/y/a/b HTTP/1.1\r\n"
10248 "Host: www.example.org\r\n"
10249 "Connection: keep-alive\r\n"
10250 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10251 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10252 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10253 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210254 };
10255
10256 // Sever accepts the authorization.
10257 MockRead data_reads1[] = {
10258 MockRead("HTTP/1.0 200 OK\r\n"),
10259 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610260 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210261 };
10262
Ryan Sleevib8d7ea02018-05-07 20:01:0110263 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710264 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210265
[email protected]49639fa2011-12-20 23:22:4110266 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210267
tfarina42834112016-09-22 13:38:2010268 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110269 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210270
10271 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110272 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210273
bnc691fda62016-08-12 00:43:1610274 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210275 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810276 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210277 }
10278}
10279
[email protected]89ceba9a2009-03-21 03:46:0610280// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110281TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610282 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910283 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610284 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610285
10286 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410287 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610288 trans.read_buf_len_ = 15;
10289 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610290
10291 // Setup state in response_
bnc691fda62016-08-12 00:43:1610292 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810293 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810294 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710295 response->response_time = base::Time::Now();
10296 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610297
10298 { // Setup state for response_.vary_data
10299 HttpRequestInfo request;
10300 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10301 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710302 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310303 request.extra_headers.SetHeader("Foo", "1");
10304 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010305 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610306 }
10307
10308 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610309 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610310
10311 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610312 EXPECT_FALSE(trans.read_buf_);
10313 EXPECT_EQ(0, trans.read_buf_len_);
10314 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810315 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210316 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410317 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810318 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710319 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610320}
10321
[email protected]bacff652009-03-31 17:50:3310322// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110323TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310324 HttpRequestInfo request;
10325 request.method = "GET";
bncce36dca22015-04-21 22:11:2310326 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010327 request.traffic_annotation =
10328 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310329
danakj1fd259a02016-04-16 03:17:0910330 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610331 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710332
[email protected]bacff652009-03-31 17:50:3310333 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310334 MockWrite(
10335 "GET / HTTP/1.1\r\n"
10336 "Host: www.example.org\r\n"
10337 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310338 };
10339
10340 MockRead data_reads[] = {
10341 MockRead("HTTP/1.0 200 OK\r\n"),
10342 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10343 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610344 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310345 };
10346
[email protected]5ecc992a42009-11-11 01:41:5910347 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110348 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610349 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10350 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310351
[email protected]bb88e1d32013-05-03 23:11:0710352 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10353 session_deps_.socket_factory->AddSocketDataProvider(&data);
10354 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10355 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310356
[email protected]49639fa2011-12-20 23:22:4110357 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310358
tfarina42834112016-09-22 13:38:2010359 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110360 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310361
10362 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110363 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310364
bnc691fda62016-08-12 00:43:1610365 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110366 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310367
10368 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110369 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310370
bnc691fda62016-08-12 00:43:1610371 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310372
wezca1070932016-05-26 20:30:5210373 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310374 EXPECT_EQ(100, response->headers->GetContentLength());
10375}
10376
10377// Test HTTPS connections to a site with a bad certificate, going through a
10378// proxy
bncd16676a2016-07-20 16:23:0110379TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610380 session_deps_.proxy_resolution_service =
10381 ConfiguredProxyResolutionService::CreateFixed(
10382 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310383
10384 HttpRequestInfo request;
10385 request.method = "GET";
bncce36dca22015-04-21 22:11:2310386 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010387 request.traffic_annotation =
10388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310389
10390 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710391 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10392 "Host: www.example.org:443\r\n"
10393 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310394 };
10395
10396 MockRead proxy_reads[] = {
10397 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610398 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310399 };
10400
10401 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710402 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10403 "Host: www.example.org:443\r\n"
10404 "Proxy-Connection: keep-alive\r\n\r\n"),
10405 MockWrite("GET / HTTP/1.1\r\n"
10406 "Host: www.example.org\r\n"
10407 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310408 };
10409
10410 MockRead data_reads[] = {
10411 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10412 MockRead("HTTP/1.0 200 OK\r\n"),
10413 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10414 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610415 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310416 };
10417
Ryan Sleevib8d7ea02018-05-07 20:01:0110418 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10419 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610420 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10421 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310422
[email protected]bb88e1d32013-05-03 23:11:0710423 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10424 session_deps_.socket_factory->AddSocketDataProvider(&data);
10425 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10426 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310427
[email protected]49639fa2011-12-20 23:22:4110428 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310429
10430 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710431 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310432
danakj1fd259a02016-04-16 03:17:0910433 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610434 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310435
tfarina42834112016-09-22 13:38:2010436 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110437 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310438
10439 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110440 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310441
bnc691fda62016-08-12 00:43:1610442 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110443 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310444
10445 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110446 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310447
bnc691fda62016-08-12 00:43:1610448 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310449
wezca1070932016-05-26 20:30:5210450 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310451 EXPECT_EQ(100, response->headers->GetContentLength());
10452 }
10453}
10454
[email protected]2df19bb2010-08-25 20:13:4610455
10456// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110457TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910458 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610459 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910460 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410461 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710462 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610463
10464 HttpRequestInfo request;
10465 request.method = "GET";
bncce36dca22015-04-21 22:11:2310466 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010467 request.traffic_annotation =
10468 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610469
10470 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710471 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10472 "Host: www.example.org:443\r\n"
10473 "Proxy-Connection: keep-alive\r\n\r\n"),
10474 MockWrite("GET / HTTP/1.1\r\n"
10475 "Host: www.example.org\r\n"
10476 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610477 };
10478
10479 MockRead data_reads[] = {
10480 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10481 MockRead("HTTP/1.1 200 OK\r\n"),
10482 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10483 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610484 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610485 };
10486
Ryan Sleevib8d7ea02018-05-07 20:01:0110487 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610488 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10489 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610490
[email protected]bb88e1d32013-05-03 23:11:0710491 session_deps_.socket_factory->AddSocketDataProvider(&data);
10492 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10493 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610494
[email protected]49639fa2011-12-20 23:22:4110495 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610496
danakj1fd259a02016-04-16 03:17:0910497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610498 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610499
tfarina42834112016-09-22 13:38:2010500 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110501 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610502
10503 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110504 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610505 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610506
wezca1070932016-05-26 20:30:5210507 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610508
tbansal2ecbbc72016-10-06 17:15:4710509 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610510 EXPECT_TRUE(response->headers->IsKeepAlive());
10511 EXPECT_EQ(200, response->headers->response_code());
10512 EXPECT_EQ(100, response->headers->GetContentLength());
10513 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010514
10515 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610516 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010517 TestLoadTimingNotReusedWithPac(load_timing_info,
10518 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610519}
10520
Eric Roman695a7872019-04-16 21:53:2910521// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110522TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910523 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610524 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910525 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410526 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710527 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910528
Matt Menkeecfecfc72019-02-05 19:15:2810529 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10530 session_deps_.host_resolver->set_ondemand_mode(true);
10531
[email protected]511f6f52010-12-17 03:58:2910532 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210533 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910534 request.method = "GET";
bncce36dca22015-04-21 22:11:2310535 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010536 request.traffic_annotation =
10537 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910538
10539 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810540 MockWrite(ASYNC, 0,
10541 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710542 "Host: www.example.org:443\r\n"
10543 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910544 };
10545
10546 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810547 // Pause on first read.
10548 MockRead(ASYNC, ERR_IO_PENDING, 1),
10549 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10550 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10551 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910552 };
10553
Matt Menkeecfecfc72019-02-05 19:15:2810554 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610555 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910556
[email protected]bb88e1d32013-05-03 23:11:0710557 session_deps_.socket_factory->AddSocketDataProvider(&data);
10558 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910559
[email protected]49639fa2011-12-20 23:22:4110560 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910561
danakj1fd259a02016-04-16 03:17:0910562 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610563 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910564
tfarina42834112016-09-22 13:38:2010565 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110566 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810567 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10568
10569 // Host resolution takes |kTimeIncrement|.
10570 FastForwardBy(kTimeIncrement);
10571 // Resolving the current request with |ResolveNow| will cause the pending
10572 // request to instantly complete, and the async connect will start as well.
10573 session_deps_.host_resolver->ResolveOnlyRequestNow();
10574
10575 // Connecting takes |kTimeIncrement|.
10576 FastForwardBy(kTimeIncrement);
10577 data.RunUntilPaused();
10578
10579 // The server takes |kTimeIncrement| to respond.
10580 FastForwardBy(kTimeIncrement);
10581 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910582
10583 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910584 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910585}
10586
Eric Roman74103c72019-02-21 00:23:1210587// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10588TEST_F(HttpNetworkTransactionTest,
10589 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10590 base::HistogramTester histograms;
10591 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610592 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Eric Roman74103c72019-02-21 00:23:1210593 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410594 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210595 session_deps_.net_log = &net_log;
10596
10597 HttpRequestInfo request;
10598 request.method = "GET";
10599 request.url = GURL("https://www.example.org/");
10600 request.traffic_annotation =
10601 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10602
10603 MockWrite data_writes[] = {
10604 MockWrite(ASYNC, 0,
10605 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10606 "Host: www.example.org:443\r\n"
10607 "Proxy-Connection: keep-alive\r\n\r\n"),
10608 };
10609
10610 MockRead data_reads[] = {
10611 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10612 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10613 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10614 };
10615
10616 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10617 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10618
10619 session_deps_.socket_factory->AddSocketDataProvider(&data);
10620 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10621
10622 TestCompletionCallback callback;
10623
10624 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10625 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10626
10627 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10628 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10629
10630 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910631 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210632}
10633
10634// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10635// request for main frames.
10636TEST_F(HttpNetworkTransactionTest,
10637 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10638 base::HistogramTester histograms;
10639 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610640 ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
Eric Roman74103c72019-02-21 00:23:1210641 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410642 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210643 session_deps_.net_log = &net_log;
10644
10645 HttpRequestInfo request;
10646 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10647 request.method = "GET";
10648 request.url = GURL("https://www.example.org/");
10649 request.traffic_annotation =
10650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10651
10652 MockWrite data_writes[] = {
10653 MockWrite(ASYNC, 0,
10654 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10655 "Host: www.example.org:443\r\n"
10656 "Proxy-Connection: keep-alive\r\n\r\n"),
10657 };
10658
10659 MockRead data_reads[] = {
10660 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10661 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10662 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10663 };
10664
10665 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10666 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10667
10668 session_deps_.socket_factory->AddSocketDataProvider(&data);
10669 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10670
10671 TestCompletionCallback callback;
10672
10673 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10675
10676 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10678
10679 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910680 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210681}
10682
Eric Roman695a7872019-04-16 21:53:2910683// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210684// frames.
bncd16676a2016-07-20 16:23:0110685TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210686 base::HistogramTester histograms;
Nicolas Arciniegad2013f92020-02-07 23:00:5610687 session_deps_.proxy_resolution_service =
10688 ConfiguredProxyResolutionService::CreateFixed(
10689 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410690 RecordingTestNetLog net_log;
Matt Menkeecfecfc72019-02-05 19:15:2810691 session_deps_.net_log = &net_log;
10692
Matt Menkeecfecfc72019-02-05 19:15:2810693 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10694 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910695
10696 HttpRequestInfo request;
10697 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210698 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310699 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010700 request.traffic_annotation =
10701 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910702
Ryan Hamilton0239aac2018-05-19 00:03:1310703 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410704 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10705 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310706 spdy::SpdySerializedFrame goaway(
10707 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910708 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110709 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810710 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910711 };
10712
10713 static const char* const kExtraHeaders[] = {
10714 "location",
10715 "http://login.example.com/",
10716 };
Ryan Hamilton0239aac2018-05-19 00:03:1310717 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410718 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910719 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810720 // Pause on first read.
10721 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10722 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910723 };
10724
Matt Menkeecfecfc72019-02-05 19:15:2810725 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610726 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610727 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910728
[email protected]bb88e1d32013-05-03 23:11:0710729 session_deps_.socket_factory->AddSocketDataProvider(&data);
10730 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910731
[email protected]49639fa2011-12-20 23:22:4110732 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910733
danakj1fd259a02016-04-16 03:17:0910734 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910736
tfarina42834112016-09-22 13:38:2010737 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810739 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2910740
Matt Menkeecfecfc72019-02-05 19:15:2810741 // Host resolution takes |kTimeIncrement|.
10742 FastForwardBy(kTimeIncrement);
10743 // Resolving the current request with |ResolveNow| will cause the pending
10744 // request to instantly complete, and the async connect will start as well.
10745 session_deps_.host_resolver->ResolveOnlyRequestNow();
10746
10747 // Connecting takes |kTimeIncrement|.
10748 FastForwardBy(kTimeIncrement);
10749 data.RunUntilPaused();
10750
10751 FastForwardBy(kTimeIncrement);
10752 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910753 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910754 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910755}
10756
[email protected]4eddbc732012-08-09 05:40:1710757// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110758TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610759 session_deps_.proxy_resolution_service =
10760 ConfiguredProxyResolutionService::CreateFixed(
10761 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910762
10763 HttpRequestInfo request;
10764 request.method = "GET";
bncce36dca22015-04-21 22:11:2310765 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010766 request.traffic_annotation =
10767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910768
10769 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710770 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10771 "Host: www.example.org:443\r\n"
10772 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910773 };
10774
10775 MockRead data_reads[] = {
10776 MockRead("HTTP/1.1 404 Not Found\r\n"),
10777 MockRead("Content-Length: 23\r\n\r\n"),
10778 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0610779 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2910780 };
10781
Ryan Sleevib8d7ea02018-05-07 20:01:0110782 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610783 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910784
[email protected]bb88e1d32013-05-03 23:11:0710785 session_deps_.socket_factory->AddSocketDataProvider(&data);
10786 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910787
[email protected]49639fa2011-12-20 23:22:4110788 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910789
danakj1fd259a02016-04-16 03:17:0910790 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610791 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910792
tfarina42834112016-09-22 13:38:2010793 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110794 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910795
10796 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110797 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910798
ttuttle960fcbf2016-04-19 13:26:3210799 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910800}
10801
[email protected]4eddbc732012-08-09 05:40:1710802// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110803TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610804 session_deps_.proxy_resolution_service =
10805 ConfiguredProxyResolutionService::CreateFixed(
10806 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910807
10808 HttpRequestInfo request;
10809 request.method = "GET";
bncce36dca22015-04-21 22:11:2310810 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010811 request.traffic_annotation =
10812 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910813
Ryan Hamilton0239aac2018-05-19 00:03:1310814 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410815 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10816 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310817 spdy::SpdySerializedFrame rst(
10818 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910819 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110820 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2910821 };
10822
10823 static const char* const kExtraHeaders[] = {
10824 "location",
10825 "http://login.example.com/",
10826 };
Ryan Hamilton0239aac2018-05-19 00:03:1310827 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410828 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1310829 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1910830 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2910831 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110832 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310833 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910834 };
10835
Ryan Sleevib8d7ea02018-05-07 20:01:0110836 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610837 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610838 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910839
[email protected]bb88e1d32013-05-03 23:11:0710840 session_deps_.socket_factory->AddSocketDataProvider(&data);
10841 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910842
[email protected]49639fa2011-12-20 23:22:4110843 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910844
danakj1fd259a02016-04-16 03:17:0910845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610846 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910847
tfarina42834112016-09-22 13:38:2010848 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110849 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910850
10851 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110852 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910853
ttuttle960fcbf2016-04-19 13:26:3210854 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910855}
10856
[email protected]0c5fb722012-02-28 11:50:3510857// Test the request-challenge-retry sequence for basic auth, through
10858// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110859TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510860 HttpRequestInfo request;
10861 request.method = "GET";
bncce36dca22015-04-21 22:11:2310862 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510863 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910864 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:1010865 request.traffic_annotation =
10866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510867
10868 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910869 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610870 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910871 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410872 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710873 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910874 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510875
10876 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310877 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410878 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10879 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310880 spdy::SpdySerializedFrame rst(
10881 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810882 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510883
bnc691fda62016-08-12 00:43:1610884 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510885 // be issuing -- the final header line contains the credentials.
10886 const char* const kAuthCredentials[] = {
10887 "proxy-authorization", "Basic Zm9vOmJhcg==",
10888 };
Ryan Hamilton0239aac2018-05-19 00:03:1310889 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410890 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10891 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310892 HostPortPair("www.example.org", 443)));
10893 // fetch https://www.example.org/ via HTTP
10894 const char get[] =
10895 "GET / HTTP/1.1\r\n"
10896 "Host: www.example.org\r\n"
10897 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310898 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910899 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510900
10901 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110902 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10903 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510904 };
10905
10906 // The proxy responds to the connect with a 407, using a persistent
10907 // connection.
thestig9d3bb0c2015-01-24 00:49:5110908 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510909 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510910 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10911 };
Ryan Hamilton0239aac2018-05-19 00:03:1310912 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410913 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510914
Ryan Hamilton0239aac2018-05-19 00:03:1310915 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510916 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510917 const char resp[] = "HTTP/1.1 200 OK\r\n"
10918 "Content-Length: 5\r\n\r\n";
10919
Ryan Hamilton0239aac2018-05-19 00:03:1310920 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910921 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310922 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910923 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510924 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110925 CreateMockRead(conn_auth_resp, 1, ASYNC),
10926 CreateMockRead(conn_resp, 4, ASYNC),
10927 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10928 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310929 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510930 };
10931
Ryan Sleevib8d7ea02018-05-07 20:01:0110932 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710933 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510934 // Negotiate SPDY to the proxy
10935 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610936 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710937 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510938 // Vanilla SSL to the server
10939 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710940 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510941
10942 TestCompletionCallback callback1;
10943
bnc87dcefc2017-05-25 12:47:5810944 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910945 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510946
10947 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510949
10950 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110951 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410952 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510953 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010954 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10955 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510956 ExpectLogContainsSomewhere(
10957 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010958 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10959 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510960
10961 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210962 ASSERT_TRUE(response);
10963 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510964 EXPECT_EQ(407, response->headers->response_code());
10965 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810966 EXPECT_TRUE(response->auth_challenge.has_value());
10967 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510968
10969 TestCompletionCallback callback2;
10970
10971 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10972 callback2.callback());
robpercival214763f2016-07-01 23:27:0110973 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510974
10975 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110976 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510977
10978 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210979 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510980
10981 EXPECT_TRUE(response->headers->IsKeepAlive());
10982 EXPECT_EQ(200, response->headers->response_code());
10983 EXPECT_EQ(5, response->headers->GetContentLength());
10984 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10985
10986 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810987 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510988
[email protected]029c83b62013-01-24 05:28:2010989 LoadTimingInfo load_timing_info;
10990 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10991 TestLoadTimingNotReusedWithPac(load_timing_info,
10992 CONNECT_TIMING_HAS_SSL_TIMES);
10993
[email protected]0c5fb722012-02-28 11:50:3510994 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1110995 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]0c5fb722012-02-28 11:50:3510996}
10997
[email protected]7c6f7ba2012-04-03 04:09:2910998// Test that an explicitly trusted SPDY proxy can push a resource from an
10999// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0111000TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1511001 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911002 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511003 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11004 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2911005 HttpRequestInfo request;
11006 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1011007 request.traffic_annotation =
11008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911009
[email protected]7c6f7ba2012-04-03 04:09:2911010 request.method = "GET";
bncce36dca22015-04-21 22:11:2311011 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2911012 push_request.method = "GET";
11013 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1011014 push_request.traffic_annotation =
11015 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911016
tbansal28e68f82016-02-04 02:56:1511017 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5911018 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611019 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911020 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411021 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711022 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011023
Eric Roman3d8546a2018-09-10 17:00:5211024 session_deps_.proxy_resolution_service->SetProxyDelegate(
11025 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011026
danakj1fd259a02016-04-16 03:17:0911027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2911028
Ryan Hamilton0239aac2018-05-19 00:03:1311029 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511030 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311031 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511032 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2911033
11034 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111035 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511036 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2911037 };
11038
Ryan Hamilton0239aac2018-05-19 00:03:1311039 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511040 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3611041
Ryan Hamilton0239aac2018-05-19 00:03:1311042 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511043 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2911044
Ryan Hamilton0239aac2018-05-19 00:03:1311045 spdy::SpdySerializedFrame stream1_body(
11046 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2911047
Ryan Hamilton0239aac2018-05-19 00:03:1311048 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1911049 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2911050
11051 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3611052 CreateMockRead(stream2_syn, 1, ASYNC),
11053 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511054 CreateMockRead(stream1_body, 4, ASYNC),
11055 CreateMockRead(stream2_body, 5, ASYNC),
11056 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2911057 };
11058
Ryan Sleevib8d7ea02018-05-07 20:01:0111059 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711060 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2911061 // Negotiate SPDY to the proxy
11062 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611063 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711064 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2911065
bnc87dcefc2017-05-25 12:47:5811066 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911067 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2911068 TestCompletionCallback callback;
11069 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111070 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911071
11072 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111073 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911074 const HttpResponseInfo* response = trans->GetResponseInfo();
11075
bnc87dcefc2017-05-25 12:47:5811076 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1911077 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5011078 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911080
11081 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111082 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911083 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
11084
wezca1070932016-05-26 20:30:5211085 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2911086 EXPECT_TRUE(response->headers->IsKeepAlive());
11087
11088 EXPECT_EQ(200, response->headers->response_code());
11089 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11090
11091 std::string response_data;
11092 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111093 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911094 EXPECT_EQ("hello!", response_data);
11095
[email protected]029c83b62013-01-24 05:28:2011096 LoadTimingInfo load_timing_info;
11097 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11098 TestLoadTimingNotReusedWithPac(load_timing_info,
11099 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11100
[email protected]7c6f7ba2012-04-03 04:09:2911101 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5211102 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2911103 EXPECT_EQ(200, push_response->headers->response_code());
11104
11105 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111106 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911107 EXPECT_EQ("pushed", response_data);
11108
[email protected]029c83b62013-01-24 05:28:2011109 LoadTimingInfo push_load_timing_info;
11110 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
11111 TestLoadTimingReusedWithPac(push_load_timing_info);
11112 // The transactions should share a socket ID, despite being for different
11113 // origins.
11114 EXPECT_EQ(load_timing_info.socket_log_id,
11115 push_load_timing_info.socket_log_id);
11116
[email protected]7c6f7ba2012-04-03 04:09:2911117 trans.reset();
11118 push_trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111119 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]7c6f7ba2012-04-03 04:09:2911120}
11121
[email protected]8c843192012-04-05 07:15:0011122// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0111123TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511124 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911125 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511126 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11127 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0011128 HttpRequestInfo request;
11129
11130 request.method = "GET";
bncce36dca22015-04-21 22:11:2311131 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011132 request.traffic_annotation =
11133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0011134
Nicolas Arciniegad2013f92020-02-07 23:00:5611135 session_deps_.proxy_resolution_service =
11136 ConfiguredProxyResolutionService::CreateFixed(
11137 "https://myproxy:443", 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();
[email protected]61b4efc2012-04-27 18:12:5011140
11141 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211142 session_deps_.proxy_resolution_service->SetProxyDelegate(
11143 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011144
danakj1fd259a02016-04-16 03:17:0911145 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0011146
Ryan Hamilton0239aac2018-05-19 00:03:1311147 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511148 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0011149
Ryan Hamilton0239aac2018-05-19 00:03:1311150 spdy::SpdySerializedFrame push_rst(
11151 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011152
11153 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111154 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011155 };
11156
Ryan Hamilton0239aac2018-05-19 00:03:1311157 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511158 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011159
Ryan Hamilton0239aac2018-05-19 00:03:1311160 spdy::SpdySerializedFrame stream1_body(
11161 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011162
Ryan Hamilton0239aac2018-05-19 00:03:1311163 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511164 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011165
11166 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111167 CreateMockRead(stream1_reply, 1, ASYNC),
11168 CreateMockRead(stream2_syn, 2, ASYNC),
11169 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911170 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011171 };
11172
Ryan Sleevib8d7ea02018-05-07 20:01:0111173 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711174 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011175 // Negotiate SPDY to the proxy
11176 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611177 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711178 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011179
bnc87dcefc2017-05-25 12:47:5811180 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911181 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011182 TestCompletionCallback callback;
11183 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011185
11186 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111187 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011188 const HttpResponseInfo* response = trans->GetResponseInfo();
11189
wezca1070932016-05-26 20:30:5211190 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011191 EXPECT_TRUE(response->headers->IsKeepAlive());
11192
11193 EXPECT_EQ(200, response->headers->response_code());
11194 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11195
11196 std::string response_data;
11197 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111198 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011199 EXPECT_EQ("hello!", response_data);
11200
11201 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111202 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]8c843192012-04-05 07:15:0011203}
11204
tbansal8ef1d3e2016-02-03 04:05:4211205// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11206// resources.
bncd16676a2016-07-20 16:23:0111207TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511208 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911209 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511210 proxy_delegate->set_trusted_spdy_proxy(
11211 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11212
tbansal8ef1d3e2016-02-03 04:05:4211213 HttpRequestInfo request;
11214
11215 request.method = "GET";
11216 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011217 request.traffic_annotation =
11218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211219
11220 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:5611221 session_deps_.proxy_resolution_service =
11222 ConfiguredProxyResolutionService::CreateFixed(
11223 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411224 RecordingBoundTestNetLog log;
tbansal8ef1d3e2016-02-03 04:05:4211225 session_deps_.net_log = log.bound().net_log();
11226
11227 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211228 session_deps_.proxy_resolution_service->SetProxyDelegate(
11229 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211230
danakj1fd259a02016-04-16 03:17:0911231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211232
Ryan Hamilton0239aac2018-05-19 00:03:1311233 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511234 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311235 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511236 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211237
11238 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111239 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511240 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211241 };
11242
Ryan Hamilton0239aac2018-05-19 00:03:1311243 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511244 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211245
Ryan Hamilton0239aac2018-05-19 00:03:1311246 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311247 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911248
Ryan Hamilton0239aac2018-05-19 00:03:1311249 spdy::SpdySerializedFrame stream1_body(
11250 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211251
Ryan Hamilton0239aac2018-05-19 00:03:1311252 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511253 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211254
Ryan Hamilton0239aac2018-05-19 00:03:1311255 spdy::SpdySerializedFrame stream2_body(
11256 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211257
11258 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111259 CreateMockRead(stream1_reply, 1, ASYNC),
11260 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511261 CreateMockRead(stream1_body, 4, ASYNC),
11262 CreateMockRead(stream2_body, 5, ASYNC),
11263 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211264 };
11265
Ryan Sleevib8d7ea02018-05-07 20:01:0111266 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211267 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11268 // Negotiate SPDY to the proxy
11269 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611270 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211271 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11272
bnc87dcefc2017-05-25 12:47:5811273 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911274 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211275 TestCompletionCallback callback;
11276 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211278
11279 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111280 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211281 const HttpResponseInfo* response = trans->GetResponseInfo();
11282
wezca1070932016-05-26 20:30:5211283 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211284 EXPECT_TRUE(response->headers->IsKeepAlive());
11285
11286 EXPECT_EQ(200, response->headers->response_code());
11287 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11288
11289 std::string response_data;
11290 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111291 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211292 EXPECT_EQ("hello!", response_data);
11293
11294 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111295 session->CloseAllConnections(ERR_FAILED, "Very good reason");
tbansal8ef1d3e2016-02-03 04:05:4211296}
11297
[email protected]2df19bb2010-08-25 20:13:4611298// Test HTTPS connections to a site with a bad certificate, going through an
11299// HTTPS proxy
bncd16676a2016-07-20 16:23:0111300TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611301 session_deps_.proxy_resolution_service =
11302 ConfiguredProxyResolutionService::CreateFixed(
11303 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611304
11305 HttpRequestInfo request;
11306 request.method = "GET";
bncce36dca22015-04-21 22:11:2311307 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011308 request.traffic_annotation =
11309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611310
11311 // Attempt to fetch the URL from a server with a bad cert
11312 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711313 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11314 "Host: www.example.org:443\r\n"
11315 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611316 };
11317
11318 MockRead bad_cert_reads[] = {
11319 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611320 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611321 };
11322
11323 // Attempt to fetch the URL with a good cert
11324 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711325 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11326 "Host: www.example.org:443\r\n"
11327 "Proxy-Connection: keep-alive\r\n\r\n"),
11328 MockWrite("GET / HTTP/1.1\r\n"
11329 "Host: www.example.org\r\n"
11330 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611331 };
11332
11333 MockRead good_cert_reads[] = {
11334 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11335 MockRead("HTTP/1.0 200 OK\r\n"),
11336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11337 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611338 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611339 };
11340
Ryan Sleevib8d7ea02018-05-07 20:01:0111341 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11342 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611343 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11344 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611345
11346 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11348 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11349 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611350
11351 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711352 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11353 session_deps_.socket_factory->AddSocketDataProvider(&data);
11354 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611355
[email protected]49639fa2011-12-20 23:22:4111356 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611357
danakj1fd259a02016-04-16 03:17:0911358 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611359 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611360
tfarina42834112016-09-22 13:38:2011361 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111362 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611363
11364 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111365 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611366
bnc691fda62016-08-12 00:43:1611367 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111368 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611369
11370 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111371 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611372
bnc691fda62016-08-12 00:43:1611373 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611374
wezca1070932016-05-26 20:30:5211375 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611376 EXPECT_EQ(100, response->headers->GetContentLength());
11377}
11378
bncd16676a2016-07-20 16:23:0111379TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211380 HttpRequestInfo request;
11381 request.method = "GET";
bncce36dca22015-04-21 22:11:2311382 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311383 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11384 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1011385 request.traffic_annotation =
11386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211387
danakj1fd259a02016-04-16 03:17:0911388 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611389 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711390
[email protected]1c773ea12009-04-28 19:58:4211391 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311392 MockWrite(
11393 "GET / HTTP/1.1\r\n"
11394 "Host: www.example.org\r\n"
11395 "Connection: keep-alive\r\n"
11396 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211397 };
11398
11399 // Lastly, the server responds with the actual content.
11400 MockRead data_reads[] = {
11401 MockRead("HTTP/1.0 200 OK\r\n"),
11402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11403 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611404 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211405 };
11406
Ryan Sleevib8d7ea02018-05-07 20:01:0111407 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711408 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211409
[email protected]49639fa2011-12-20 23:22:4111410 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211411
tfarina42834112016-09-22 13:38:2011412 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111413 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211414
11415 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111416 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211417}
11418
bncd16676a2016-07-20 16:23:0111419TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011420 // Test user agent values, used both for the request header of the original
11421 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11422 // no request header / no HttpUserAgentSettings object.
11423 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911424
Matt Menked732ea42019-03-08 12:05:0011425 for (const char* setting_user_agent : kTestUserAgents) {
11426 if (!setting_user_agent) {
11427 session_deps_.http_user_agent_settings.reset();
11428 } else {
11429 session_deps_.http_user_agent_settings =
11430 std::make_unique<StaticHttpUserAgentSettings>(
11431 std::string() /* accept-language */, setting_user_agent);
11432 }
11433 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611434 ConfiguredProxyResolutionService::CreateFixed(
11435 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked732ea42019-03-08 12:05:0011436 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11437 for (const char* request_user_agent : kTestUserAgents) {
11438 HttpRequestInfo request;
11439 request.method = "GET";
11440 request.url = GURL("https://www.example.org/");
11441 if (request_user_agent) {
11442 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11443 request_user_agent);
11444 }
11445 request.traffic_annotation =
11446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711447
Matt Menked732ea42019-03-08 12:05:0011448 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911449
Matt Menked732ea42019-03-08 12:05:0011450 std::string expected_request;
11451 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11452 expected_request =
11453 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11454 "Host: www.example.org:443\r\n"
11455 "Proxy-Connection: keep-alive\r\n\r\n";
11456 } else {
11457 expected_request = base::StringPrintf(
11458 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11459 "Host: www.example.org:443\r\n"
11460 "Proxy-Connection: keep-alive\r\n"
11461 "User-Agent: %s\r\n\r\n",
11462 setting_user_agent);
11463 }
11464 MockWrite data_writes[] = {
11465 MockWrite(expected_request.c_str()),
11466 };
11467 MockRead data_reads[] = {
11468 // Return an error, so the transaction stops here (this test isn't
11469 // interested in the rest).
11470 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11471 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11472 MockRead("Proxy-Connection: close\r\n\r\n"),
11473 };
[email protected]da81f132010-08-18 23:39:2911474
Matt Menked732ea42019-03-08 12:05:0011475 StaticSocketDataProvider data(data_reads, data_writes);
11476 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911477
Matt Menked732ea42019-03-08 12:05:0011478 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911479
Matt Menked732ea42019-03-08 12:05:0011480 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11482
11483 rv = callback.WaitForResult();
11484 EXPECT_THAT(rv, IsOk());
11485 }
11486 }
[email protected]da81f132010-08-18 23:39:2911487}
11488
bncd16676a2016-07-20 16:23:0111489TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211490 HttpRequestInfo request;
11491 request.method = "GET";
bncce36dca22015-04-21 22:11:2311492 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611493 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11494 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011495 request.traffic_annotation =
11496 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211497
danakj1fd259a02016-04-16 03:17:0911498 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611499 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711500
[email protected]1c773ea12009-04-28 19:58:4211501 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311502 MockWrite(
11503 "GET / HTTP/1.1\r\n"
11504 "Host: www.example.org\r\n"
11505 "Connection: keep-alive\r\n"
11506 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211507 };
11508
11509 // Lastly, the server responds with the actual content.
11510 MockRead data_reads[] = {
11511 MockRead("HTTP/1.0 200 OK\r\n"),
11512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11513 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611514 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211515 };
11516
Ryan Sleevib8d7ea02018-05-07 20:01:0111517 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711518 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211519
[email protected]49639fa2011-12-20 23:22:4111520 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211521
tfarina42834112016-09-22 13:38:2011522 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211524
11525 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111526 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211527}
11528
bncd16676a2016-07-20 16:23:0111529TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211530 HttpRequestInfo request;
11531 request.method = "POST";
bncce36dca22015-04-21 22:11:2311532 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011533 request.traffic_annotation =
11534 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211535
danakj1fd259a02016-04-16 03:17:0911536 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611537 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711538
[email protected]1c773ea12009-04-28 19:58:4211539 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311540 MockWrite(
11541 "POST / HTTP/1.1\r\n"
11542 "Host: www.example.org\r\n"
11543 "Connection: keep-alive\r\n"
11544 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211545 };
11546
11547 // Lastly, the server responds with the actual content.
11548 MockRead data_reads[] = {
11549 MockRead("HTTP/1.0 200 OK\r\n"),
11550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11551 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611552 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211553 };
11554
Ryan Sleevib8d7ea02018-05-07 20:01:0111555 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711556 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211557
[email protected]49639fa2011-12-20 23:22:4111558 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211559
tfarina42834112016-09-22 13:38:2011560 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111561 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211562
11563 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111564 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211565}
11566
bncd16676a2016-07-20 16:23:0111567TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211568 HttpRequestInfo request;
11569 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311570 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011571 request.traffic_annotation =
11572 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211573
danakj1fd259a02016-04-16 03:17:0911574 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611575 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711576
[email protected]1c773ea12009-04-28 19:58:4211577 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311578 MockWrite(
11579 "PUT / HTTP/1.1\r\n"
11580 "Host: www.example.org\r\n"
11581 "Connection: keep-alive\r\n"
11582 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211583 };
11584
11585 // Lastly, the server responds with the actual content.
11586 MockRead data_reads[] = {
11587 MockRead("HTTP/1.0 200 OK\r\n"),
11588 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11589 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611590 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211591 };
11592
Ryan Sleevib8d7ea02018-05-07 20:01:0111593 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711594 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211595
[email protected]49639fa2011-12-20 23:22:4111596 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211597
tfarina42834112016-09-22 13:38:2011598 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111599 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211600
11601 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111602 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211603}
11604
bncd16676a2016-07-20 16:23:0111605TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211606 HttpRequestInfo request;
11607 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311608 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011609 request.traffic_annotation =
11610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211611
danakj1fd259a02016-04-16 03:17:0911612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611613 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711614
[email protected]1c773ea12009-04-28 19:58:4211615 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311616 MockWrite("HEAD / HTTP/1.1\r\n"
11617 "Host: www.example.org\r\n"
11618 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211619 };
11620
11621 // Lastly, the server responds with the actual content.
11622 MockRead data_reads[] = {
11623 MockRead("HTTP/1.0 200 OK\r\n"),
11624 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11625 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611626 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211627 };
11628
Ryan Sleevib8d7ea02018-05-07 20:01:0111629 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711630 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211631
[email protected]49639fa2011-12-20 23:22:4111632 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211633
tfarina42834112016-09-22 13:38:2011634 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111635 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211636
11637 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111638 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211639}
11640
bncd16676a2016-07-20 16:23:0111641TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211642 HttpRequestInfo request;
11643 request.method = "GET";
bncce36dca22015-04-21 22:11:2311644 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211645 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011646 request.traffic_annotation =
11647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211648
danakj1fd259a02016-04-16 03:17:0911649 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611650 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711651
[email protected]1c773ea12009-04-28 19:58:4211652 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311653 MockWrite(
11654 "GET / HTTP/1.1\r\n"
11655 "Host: www.example.org\r\n"
11656 "Connection: keep-alive\r\n"
11657 "Pragma: no-cache\r\n"
11658 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211659 };
11660
11661 // Lastly, the server responds with the actual content.
11662 MockRead data_reads[] = {
11663 MockRead("HTTP/1.0 200 OK\r\n"),
11664 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11665 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611666 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211667 };
11668
Ryan Sleevib8d7ea02018-05-07 20:01:0111669 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711670 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211671
[email protected]49639fa2011-12-20 23:22:4111672 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211673
tfarina42834112016-09-22 13:38:2011674 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211676
11677 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111678 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211679}
11680
bncd16676a2016-07-20 16:23:0111681TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211682 HttpRequestInfo request;
11683 request.method = "GET";
bncce36dca22015-04-21 22:11:2311684 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211685 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011686 request.traffic_annotation =
11687 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211688
danakj1fd259a02016-04-16 03:17:0911689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611690 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711691
[email protected]1c773ea12009-04-28 19:58:4211692 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311693 MockWrite(
11694 "GET / HTTP/1.1\r\n"
11695 "Host: www.example.org\r\n"
11696 "Connection: keep-alive\r\n"
11697 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211698 };
11699
11700 // Lastly, the server responds with the actual content.
11701 MockRead data_reads[] = {
11702 MockRead("HTTP/1.0 200 OK\r\n"),
11703 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11704 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611705 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211706 };
11707
Ryan Sleevib8d7ea02018-05-07 20:01:0111708 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711709 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211710
[email protected]49639fa2011-12-20 23:22:4111711 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211712
tfarina42834112016-09-22 13:38:2011713 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111714 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211715
11716 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111717 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211718}
11719
bncd16676a2016-07-20 16:23:0111720TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211721 HttpRequestInfo request;
11722 request.method = "GET";
bncce36dca22015-04-21 22:11:2311723 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311724 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1011725 request.traffic_annotation =
11726 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211727
danakj1fd259a02016-04-16 03:17:0911728 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611729 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711730
[email protected]1c773ea12009-04-28 19:58:4211731 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311732 MockWrite(
11733 "GET / HTTP/1.1\r\n"
11734 "Host: www.example.org\r\n"
11735 "Connection: keep-alive\r\n"
11736 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211737 };
11738
11739 // Lastly, the server responds with the actual content.
11740 MockRead data_reads[] = {
11741 MockRead("HTTP/1.0 200 OK\r\n"),
11742 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11743 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611744 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211745 };
11746
Ryan Sleevib8d7ea02018-05-07 20:01:0111747 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711748 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211749
[email protected]49639fa2011-12-20 23:22:4111750 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211751
tfarina42834112016-09-22 13:38:2011752 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211754
11755 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111756 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211757}
11758
bncd16676a2016-07-20 16:23:0111759TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4711760 HttpRequestInfo request;
11761 request.method = "GET";
bncce36dca22015-04-21 22:11:2311762 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311763 request.extra_headers.SetHeader("referer", "www.foo.com");
11764 request.extra_headers.SetHeader("hEllo", "Kitty");
11765 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1011766 request.traffic_annotation =
11767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4711768
danakj1fd259a02016-04-16 03:17:0911769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611770 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711771
[email protected]270c6412010-03-29 22:02:4711772 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311773 MockWrite(
11774 "GET / HTTP/1.1\r\n"
11775 "Host: www.example.org\r\n"
11776 "Connection: keep-alive\r\n"
11777 "referer: www.foo.com\r\n"
11778 "hEllo: Kitty\r\n"
11779 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4711780 };
11781
11782 // Lastly, the server responds with the actual content.
11783 MockRead data_reads[] = {
11784 MockRead("HTTP/1.0 200 OK\r\n"),
11785 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11786 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611787 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4711788 };
11789
Ryan Sleevib8d7ea02018-05-07 20:01:0111790 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711791 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4711792
[email protected]49639fa2011-12-20 23:22:4111793 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4711794
tfarina42834112016-09-22 13:38:2011795 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111796 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4711797
11798 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111799 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4711800}
11801
bncd16676a2016-07-20 16:23:0111802TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711803 HttpRequestInfo request;
11804 request.method = "GET";
bncce36dca22015-04-21 22:11:2311805 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011806 request.traffic_annotation =
11807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711808
Lily Houghton8c2f97d2018-01-22 05:06:5911809 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611810 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911811 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411812 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711813 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211814
danakj1fd259a02016-04-16 03:17:0911815 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611816 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211817
[email protected]3cd17242009-06-23 02:59:0211818 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11819 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11820
11821 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411822 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11823 MockWrite("GET / HTTP/1.1\r\n"
11824 "Host: www.example.org\r\n"
11825 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211826
11827 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411828 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11829 MockRead("HTTP/1.0 200 OK\r\n"),
11830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11831 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211832
Ryan Sleevib8d7ea02018-05-07 20:01:0111833 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711834 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211835
[email protected]49639fa2011-12-20 23:22:4111836 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211837
tfarina42834112016-09-22 13:38:2011838 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211840
11841 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111842 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211843
bnc691fda62016-08-12 00:43:1611844 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211845 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211846
tbansal2ecbbc72016-10-06 17:15:4711847 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011848 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611849 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011850 TestLoadTimingNotReusedWithPac(load_timing_info,
11851 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11852
[email protected]3cd17242009-06-23 02:59:0211853 std::string response_text;
bnc691fda62016-08-12 00:43:1611854 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111855 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211856 EXPECT_EQ("Payload", response_text);
11857}
11858
bncd16676a2016-07-20 16:23:0111859TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711860 HttpRequestInfo request;
11861 request.method = "GET";
bncce36dca22015-04-21 22:11:2311862 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011863 request.traffic_annotation =
11864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711865
Lily Houghton8c2f97d2018-01-22 05:06:5911866 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611867 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911868 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411869 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711870 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211871
danakj1fd259a02016-04-16 03:17:0911872 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611873 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211874
[email protected]3cd17242009-06-23 02:59:0211875 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11876 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11877
11878 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311879 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411880 base::size(write_buffer)),
11881 MockWrite("GET / HTTP/1.1\r\n"
11882 "Host: www.example.org\r\n"
11883 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211884
11885 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411886 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11887 base::size(read_buffer)),
11888 MockRead("HTTP/1.0 200 OK\r\n"),
11889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11890 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511891
Ryan Sleevib8d7ea02018-05-07 20:01:0111892 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711893 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511894
[email protected]8ddf8322012-02-23 18:08:0611895 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511897
[email protected]49639fa2011-12-20 23:22:4111898 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511899
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]e0c27be2009-07-15 13:09:3511902
11903 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111904 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511905
[email protected]029c83b62013-01-24 05:28:2011906 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611907 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011908 TestLoadTimingNotReusedWithPac(load_timing_info,
11909 CONNECT_TIMING_HAS_SSL_TIMES);
11910
bnc691fda62016-08-12 00:43:1611911 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211912 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711913 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511914
11915 std::string response_text;
bnc691fda62016-08-12 00:43:1611916 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111917 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511918 EXPECT_EQ("Payload", response_text);
11919}
11920
bncd16676a2016-07-20 16:23:0111921TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011922 HttpRequestInfo request;
11923 request.method = "GET";
bncce36dca22015-04-21 22:11:2311924 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011925 request.traffic_annotation =
11926 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011927
Nicolas Arciniegad2013f92020-02-07 23:00:5611928 session_deps_.proxy_resolution_service =
11929 ConfiguredProxyResolutionService::CreateFixed(
11930 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411931 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711932 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011933
danakj1fd259a02016-04-16 03:17:0911934 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611935 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011936
11937 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11938 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11939
11940 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411941 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11942 MockWrite("GET / HTTP/1.1\r\n"
11943 "Host: www.example.org\r\n"
11944 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011945
11946 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411947 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11948 MockRead("HTTP/1.0 200 OK\r\n"),
11949 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11950 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011951
Ryan Sleevib8d7ea02018-05-07 20:01:0111952 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711953 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011954
11955 TestCompletionCallback callback;
11956
tfarina42834112016-09-22 13:38:2011957 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111958 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011959
11960 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111961 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011962
bnc691fda62016-08-12 00:43:1611963 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211964 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011965
11966 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611967 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011968 TestLoadTimingNotReused(load_timing_info,
11969 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11970
11971 std::string response_text;
bnc691fda62016-08-12 00:43:1611972 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111973 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011974 EXPECT_EQ("Payload", response_text);
11975}
11976
bncd16676a2016-07-20 16:23:0111977TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711978 HttpRequestInfo request;
11979 request.method = "GET";
bncce36dca22015-04-21 22:11:2311980 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011981 request.traffic_annotation =
11982 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711983
Lily Houghton8c2f97d2018-01-22 05:06:5911984 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611985 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911986 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411987 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711988 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511989
danakj1fd259a02016-04-16 03:17:0911990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611991 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511992
[email protected]e0c27be2009-07-15 13:09:3511993 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11994 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711995 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311996 0x05, // Version
11997 0x01, // Command (CONNECT)
11998 0x00, // Reserved.
11999 0x03, // Address type (DOMAINNAME).
12000 0x0F, // Length of domain (15)
12001 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12002 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3712003 };
[email protected]e0c27be2009-07-15 13:09:3512004 const char kSOCKS5OkResponse[] =
12005 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
12006
12007 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412008 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
12009 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
12010 MockWrite("GET / HTTP/1.1\r\n"
12011 "Host: www.example.org\r\n"
12012 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512013
12014 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412015 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12016 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12017 MockRead("HTTP/1.0 200 OK\r\n"),
12018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12019 MockRead("Payload"),
12020 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512021
Ryan Sleevib8d7ea02018-05-07 20:01:0112022 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712023 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512024
[email protected]49639fa2011-12-20 23:22:4112025 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512026
tfarina42834112016-09-22 13:38:2012027 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112028 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512029
12030 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112031 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512032
bnc691fda62016-08-12 00:43:1612033 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212034 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712035 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512036
[email protected]029c83b62013-01-24 05:28:2012037 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612038 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012039 TestLoadTimingNotReusedWithPac(load_timing_info,
12040 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12041
[email protected]e0c27be2009-07-15 13:09:3512042 std::string response_text;
bnc691fda62016-08-12 00:43:1612043 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112044 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512045 EXPECT_EQ("Payload", response_text);
12046}
12047
bncd16676a2016-07-20 16:23:0112048TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712049 HttpRequestInfo request;
12050 request.method = "GET";
bncce36dca22015-04-21 22:11:2312051 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012052 request.traffic_annotation =
12053 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712054
Lily Houghton8c2f97d2018-01-22 05:06:5912055 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612056 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912057 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412058 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712059 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512060
danakj1fd259a02016-04-16 03:17:0912061 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612062 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512063
[email protected]e0c27be2009-07-15 13:09:3512064 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12065 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712066 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312067 0x05, // Version
12068 0x01, // Command (CONNECT)
12069 0x00, // Reserved.
12070 0x03, // Address type (DOMAINNAME).
12071 0x0F, // Length of domain (15)
12072 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12073 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3712074 };
12075
[email protected]e0c27be2009-07-15 13:09:3512076 const char kSOCKS5OkResponse[] =
12077 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
12078
12079 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412080 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2312081 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2412082 base::size(kSOCKS5OkRequest)),
12083 MockWrite("GET / HTTP/1.1\r\n"
12084 "Host: www.example.org\r\n"
12085 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512086
12087 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412088 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12089 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12090 MockRead("HTTP/1.0 200 OK\r\n"),
12091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12092 MockRead("Payload"),
12093 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212094
Ryan Sleevib8d7ea02018-05-07 20:01:0112095 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712096 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212097
[email protected]8ddf8322012-02-23 18:08:0612098 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712099 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0212100
[email protected]49639fa2011-12-20 23:22:4112101 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212102
tfarina42834112016-09-22 13:38:2012103 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212105
12106 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112107 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212108
bnc691fda62016-08-12 00:43:1612109 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212110 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712111 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0212112
[email protected]029c83b62013-01-24 05:28:2012113 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612114 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012115 TestLoadTimingNotReusedWithPac(load_timing_info,
12116 CONNECT_TIMING_HAS_SSL_TIMES);
12117
[email protected]3cd17242009-06-23 02:59:0212118 std::string response_text;
bnc691fda62016-08-12 00:43:1612119 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112120 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212121 EXPECT_EQ("Payload", response_text);
12122}
12123
[email protected]448d4ca52012-03-04 04:12:2312124namespace {
12125
Matt Menkef6edce752019-03-19 17:21:5612126// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0612127
Matt Menkef6edce752019-03-19 17:21:5612128struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0612129 std::string proxy_server;
12130 std::string url;
Matt Menkef6edce752019-03-19 17:21:5612131 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1812132 bool ssl;
[email protected]2d731a32010-04-29 01:04:0612133};
12134
Matt Menkef6edce752019-03-19 17:21:5612135std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0712136 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0912137 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0612138
bnc525e175a2016-06-20 12:36:4012139 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312140 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112141 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1212142 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112143 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4212144 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0712145 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0612146
12147 return session;
12148}
12149
Matt Menkef6edce752019-03-19 17:21:5612150int GroupIdTransactionHelper(const std::string& url,
12151 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0612152 HttpRequestInfo request;
12153 request.method = "GET";
12154 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1012155 request.traffic_annotation =
12156 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612157
bnc691fda62016-08-12 00:43:1612158 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712159
[email protected]49639fa2011-12-20 23:22:4112160 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612161
12162 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012163 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612164}
12165
[email protected]448d4ca52012-03-04 04:12:2312166} // namespace
12167
Matt Menkef6edce752019-03-19 17:21:5612168TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12169 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312170 {
Matt Menkef6edce752019-03-19 17:21:5612171 "", // unused
12172 "http://www.example.org/direct",
12173 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12174 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412175 PrivacyMode::PRIVACY_MODE_DISABLED,
12176 NetworkIsolationKey(),
12177 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612178 false,
bncce36dca22015-04-21 22:11:2312179 },
12180 {
Matt Menkef6edce752019-03-19 17:21:5612181 "", // unused
12182 "http://[2001:1418:13:1::25]/direct",
12183 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12184 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412185 PrivacyMode::PRIVACY_MODE_DISABLED,
12186 NetworkIsolationKey(),
12187 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612188 false,
bncce36dca22015-04-21 22:11:2312189 },
[email protected]04e5be32009-06-26 20:00:3112190
bncce36dca22015-04-21 22:11:2312191 // SSL Tests
12192 {
Matt Menkef6edce752019-03-19 17:21:5612193 "", // unused
12194 "https://www.example.org/direct_ssl",
12195 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12196 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412197 PrivacyMode::PRIVACY_MODE_DISABLED,
12198 NetworkIsolationKey(),
12199 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612200 true,
bncce36dca22015-04-21 22:11:2312201 },
12202 {
Matt Menkef6edce752019-03-19 17:21:5612203 "", // unused
12204 "https://[2001:1418:13:1::25]/direct",
12205 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12206 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412207 PrivacyMode::PRIVACY_MODE_DISABLED,
12208 NetworkIsolationKey(),
12209 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612210 true,
bncce36dca22015-04-21 22:11:2312211 },
12212 {
Matt Menkef6edce752019-03-19 17:21:5612213 "", // unused
12214 "https://host.with.alternate/direct",
12215 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12216 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412217 PrivacyMode::PRIVACY_MODE_DISABLED,
12218 NetworkIsolationKey(),
12219 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612220 true,
bncce36dca22015-04-21 22:11:2312221 },
[email protected]2d731a32010-04-29 01:04:0612222 };
[email protected]2ff8b312010-04-26 22:20:5412223
Avi Drissman4365a4782018-12-28 19:26:2412224 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912225 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612226 ConfiguredProxyResolutionService::CreateFixed(
12227 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912228 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612229 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612230
mmenkee65e7af2015-10-13 17:16:4212231 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612232 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612233 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912234 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012235 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12236 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812237 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612238
12239 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612240 GroupIdTransactionHelper(tests[i].url, session.get()));
12241 EXPECT_EQ(tests[i].expected_group_id,
12242 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312243 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612244 }
[email protected]2d731a32010-04-29 01:04:0612245}
12246
Matt Menkef6edce752019-03-19 17:21:5612247TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12248 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312249 {
Matt Menke4802de62019-03-08 22:47:5012250 "http_proxy",
12251 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612252 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12253 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412254 PrivacyMode::PRIVACY_MODE_DISABLED,
12255 NetworkIsolationKey(),
12256 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012257 false,
bncce36dca22015-04-21 22:11:2312258 },
[email protected]2d731a32010-04-29 01:04:0612259
bncce36dca22015-04-21 22:11:2312260 // SSL Tests
12261 {
Matt Menke4802de62019-03-08 22:47:5012262 "http_proxy",
12263 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612264 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12265 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412266 PrivacyMode::PRIVACY_MODE_DISABLED,
12267 NetworkIsolationKey(),
12268 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012269 true,
bncce36dca22015-04-21 22:11:2312270 },
[email protected]af3490e2010-10-16 21:02:2912271
bncce36dca22015-04-21 22:11:2312272 {
Matt Menke4802de62019-03-08 22:47:5012273 "http_proxy",
12274 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612275 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12276 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412277 PrivacyMode::PRIVACY_MODE_DISABLED,
12278 NetworkIsolationKey(),
12279 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012280 true,
bncce36dca22015-04-21 22:11:2312281 },
[email protected]2d731a32010-04-29 01:04:0612282 };
12283
Avi Drissman4365a4782018-12-28 19:26:2412284 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912285 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612286 ConfiguredProxyResolutionService::CreateFixed(
12287 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912288 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612289 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612290
mmenkee65e7af2015-10-13 17:16:4212291 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612292
Matt Menkee8648fa2019-01-17 16:47:0712293 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12294 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612295 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612296 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912297 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012298 mock_pool_manager->SetSocketPool(proxy_server,
12299 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812300 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612301
12302 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612303 GroupIdTransactionHelper(tests[i].url, session.get()));
12304 EXPECT_EQ(tests[i].expected_group_id,
12305 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612306 }
[email protected]2d731a32010-04-29 01:04:0612307}
12308
Matt Menkef6edce752019-03-19 17:21:5612309TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12310 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312311 {
Matt Menke4802de62019-03-08 22:47:5012312 "socks4://socks_proxy:1080",
12313 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612314 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12315 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412316 PrivacyMode::PRIVACY_MODE_DISABLED,
12317 NetworkIsolationKey(),
12318 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012319 false,
bncce36dca22015-04-21 22:11:2312320 },
12321 {
Matt Menke4802de62019-03-08 22:47:5012322 "socks5://socks_proxy:1080",
12323 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612324 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12325 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412326 PrivacyMode::PRIVACY_MODE_DISABLED,
12327 NetworkIsolationKey(),
12328 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012329 false,
bncce36dca22015-04-21 22:11:2312330 },
[email protected]2d731a32010-04-29 01:04:0612331
bncce36dca22015-04-21 22:11:2312332 // SSL Tests
12333 {
Matt Menke4802de62019-03-08 22:47:5012334 "socks4://socks_proxy:1080",
12335 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612336 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12337 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412338 PrivacyMode::PRIVACY_MODE_DISABLED,
12339 NetworkIsolationKey(),
12340 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012341 true,
bncce36dca22015-04-21 22:11:2312342 },
12343 {
Matt Menke4802de62019-03-08 22:47:5012344 "socks5://socks_proxy:1080",
12345 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612346 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12347 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412348 PrivacyMode::PRIVACY_MODE_DISABLED,
12349 NetworkIsolationKey(),
12350 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012351 true,
bncce36dca22015-04-21 22:11:2312352 },
[email protected]af3490e2010-10-16 21:02:2912353
bncce36dca22015-04-21 22:11:2312354 {
Matt Menke4802de62019-03-08 22:47:5012355 "socks4://socks_proxy:1080",
12356 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612357 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12358 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412359 PrivacyMode::PRIVACY_MODE_DISABLED,
12360 NetworkIsolationKey(),
12361 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012362 true,
bncce36dca22015-04-21 22:11:2312363 },
[email protected]04e5be32009-06-26 20:00:3112364 };
12365
Avi Drissman4365a4782018-12-28 19:26:2412366 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912367 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612368 ConfiguredProxyResolutionService::CreateFixed(
12369 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912370 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612371 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212372
mmenkee65e7af2015-10-13 17:16:4212373 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112374
Matt Menkee8648fa2019-01-17 16:47:0712375 ProxyServer proxy_server(
12376 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12377 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612378 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612379 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912380 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012381 mock_pool_manager->SetSocketPool(proxy_server,
12382 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812383 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112384
bnc691fda62016-08-12 00:43:1612385 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112386
[email protected]2d731a32010-04-29 01:04:0612387 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612388 GroupIdTransactionHelper(tests[i].url, session.get()));
12389 EXPECT_EQ(tests[i].expected_group_id,
12390 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112391 }
12392}
12393
bncd16676a2016-07-20 16:23:0112394TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712395 HttpRequestInfo request;
12396 request.method = "GET";
bncce36dca22015-04-21 22:11:2312397 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012398 request.traffic_annotation =
12399 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712400
Nicolas Arciniegad2013f92020-02-07 23:00:5612401 session_deps_.proxy_resolution_service =
12402 ConfiguredProxyResolutionService::CreateFixed(
12403 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212404
[email protected]69719062010-01-05 20:09:2112405 // This simulates failure resolving all hostnames; that means we will fail
12406 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712407 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212408
danakj1fd259a02016-04-16 03:17:0912409 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612410 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512411
[email protected]49639fa2011-12-20 23:22:4112412 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512413
tfarina42834112016-09-22 13:38:2012414 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112415 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512416
[email protected]9172a982009-06-06 00:30:2512417 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112418 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512419}
12420
[email protected]0877e3d2009-10-17 22:29:5712421// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112422TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712423 HttpRequestInfo request;
12424 request.method = "GET";
12425 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012426 request.traffic_annotation =
12427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712428
12429 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612430 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712431 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112432 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712433 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912434 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712435
[email protected]49639fa2011-12-20 23:22:4112436 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712437
bnc691fda62016-08-12 00:43:1612438 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712439
tfarina42834112016-09-22 13:38:2012440 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112441 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712442
12443 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112444 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912445
12446 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612447 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912448 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712449}
12450
zmo9528c9f42015-08-04 22:12:0812451// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112452TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712453 HttpRequestInfo request;
12454 request.method = "GET";
12455 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012456 request.traffic_annotation =
12457 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712458
12459 MockRead data_reads[] = {
12460 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612461 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712462 };
12463
Ryan Sleevib8d7ea02018-05-07 20:01:0112464 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712465 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912466 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712467
[email protected]49639fa2011-12-20 23:22:4112468 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712469
bnc691fda62016-08-12 00:43:1612470 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712471
tfarina42834112016-09-22 13:38:2012472 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112473 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712474
12475 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112476 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812477
bnc691fda62016-08-12 00:43:1612478 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212479 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812480
wezca1070932016-05-26 20:30:5212481 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812482 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12483
12484 std::string response_data;
bnc691fda62016-08-12 00:43:1612485 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112486 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812487 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912488
12489 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612490 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912491 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712492}
12493
12494// Make sure that a dropped connection while draining the body for auth
12495// restart does the right thing.
bncd16676a2016-07-20 16:23:0112496TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712497 HttpRequestInfo request;
12498 request.method = "GET";
bncce36dca22015-04-21 22:11:2312499 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012500 request.traffic_annotation =
12501 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712502
12503 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312504 MockWrite(
12505 "GET / HTTP/1.1\r\n"
12506 "Host: www.example.org\r\n"
12507 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712508 };
12509
12510 MockRead data_reads1[] = {
12511 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12512 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12513 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12514 MockRead("Content-Length: 14\r\n\r\n"),
12515 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612516 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712517 };
12518
Ryan Sleevib8d7ea02018-05-07 20:01:0112519 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712520 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712521
bnc691fda62016-08-12 00:43:1612522 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712523 // be issuing -- the final header line contains the credentials.
12524 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312525 MockWrite(
12526 "GET / HTTP/1.1\r\n"
12527 "Host: www.example.org\r\n"
12528 "Connection: keep-alive\r\n"
12529 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712530 };
12531
12532 // Lastly, the server responds with the actual content.
12533 MockRead data_reads2[] = {
12534 MockRead("HTTP/1.1 200 OK\r\n"),
12535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12536 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612537 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712538 };
12539
Ryan Sleevib8d7ea02018-05-07 20:01:0112540 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712541 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912542 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712543
[email protected]49639fa2011-12-20 23:22:4112544 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712545
bnc691fda62016-08-12 00:43:1612546 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012547
tfarina42834112016-09-22 13:38:2012548 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112549 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712550
12551 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112552 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712553
bnc691fda62016-08-12 00:43:1612554 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212555 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812556 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712557
[email protected]49639fa2011-12-20 23:22:4112558 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712559
bnc691fda62016-08-12 00:43:1612560 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112561 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712562
12563 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112564 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712565
bnc691fda62016-08-12 00:43:1612566 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212567 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812568 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712569 EXPECT_EQ(100, response->headers->GetContentLength());
12570}
12571
12572// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112573TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Nicolas Arciniegad2013f92020-02-07 23:00:5612574 session_deps_.proxy_resolution_service =
12575 ConfiguredProxyResolutionService::CreateFixed(
12576 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712577
12578 HttpRequestInfo request;
12579 request.method = "GET";
bncce36dca22015-04-21 22:11:2312580 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012581 request.traffic_annotation =
12582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712583
12584 MockRead proxy_reads[] = {
12585 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612586 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712587 };
12588
Ryan Sleevib8d7ea02018-05-07 20:01:0112589 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612590 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712591
[email protected]bb88e1d32013-05-03 23:11:0712592 session_deps_.socket_factory->AddSocketDataProvider(&data);
12593 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712594
[email protected]49639fa2011-12-20 23:22:4112595 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712596
[email protected]bb88e1d32013-05-03 23:11:0712597 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712598
danakj1fd259a02016-04-16 03:17:0912599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712601
tfarina42834112016-09-22 13:38:2012602 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112603 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712604
12605 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112606 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712607}
12608
bncd16676a2016-07-20 16:23:0112609TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612610 HttpRequestInfo request;
12611 request.method = "GET";
bncce36dca22015-04-21 22:11:2312612 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012613 request.traffic_annotation =
12614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612615
danakj1fd259a02016-04-16 03:17:0912616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612617 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712618
[email protected]e22e1362009-11-23 21:31:1212619 MockRead data_reads[] = {
12620 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612621 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212622 };
[email protected]9492e4a2010-02-24 00:58:4612623
Ryan Sleevib8d7ea02018-05-07 20:01:0112624 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712625 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612626
[email protected]49639fa2011-12-20 23:22:4112627 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612628
tfarina42834112016-09-22 13:38:2012629 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112630 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612631
robpercival214763f2016-07-01 23:27:0112632 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612633
bnc691fda62016-08-12 00:43:1612634 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212635 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612636
wezca1070932016-05-26 20:30:5212637 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612638 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12639
12640 std::string response_data;
bnc691fda62016-08-12 00:43:1612641 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112642 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212643}
12644
bncd16676a2016-07-20 16:23:0112645TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512646 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212647 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412648 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112649 UploadFileElementReader::ScopedOverridingContentLengthForTests
12650 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312651
danakj1fd259a02016-04-16 03:17:0912652 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912653 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412654 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712655 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212656 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712657
12658 HttpRequestInfo request;
12659 request.method = "POST";
bncce36dca22015-04-21 22:11:2312660 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712661 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012662 request.traffic_annotation =
12663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712664
danakj1fd259a02016-04-16 03:17:0912665 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612666 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312667
12668 MockRead data_reads[] = {
12669 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12670 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612671 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312672 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112673 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712674 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312675
[email protected]49639fa2011-12-20 23:22:4112676 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312677
tfarina42834112016-09-22 13:38:2012678 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112679 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312680
12681 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112682 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312683
bnc691fda62016-08-12 00:43:1612684 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212685 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312686
maksim.sisove869bf52016-06-23 17:11:5212687 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312688
[email protected]dd3aa792013-07-16 19:10:2312689 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3312690}
12691
bncd16676a2016-07-20 16:23:0112692TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512693 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212694 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612695 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812696 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12697 base::WriteFile(temp_file, temp_file_content.c_str(),
12698 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112699 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612700
danakj1fd259a02016-04-16 03:17:0912701 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912702 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412703 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712704 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212705 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712706
12707 HttpRequestInfo request;
12708 request.method = "POST";
bncce36dca22015-04-21 22:11:2312709 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712710 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012711 request.traffic_annotation =
12712 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712713
[email protected]999dd8c2013-11-12 06:45:5412714 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912715 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612716 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612717
Ryan Sleevib8d7ea02018-05-07 20:01:0112718 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712719 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612720
[email protected]49639fa2011-12-20 23:22:4112721 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612722
tfarina42834112016-09-22 13:38:2012723 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612725
12726 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112727 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612728
[email protected]dd3aa792013-07-16 19:10:2312729 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3612730}
12731
bncd16676a2016-07-20 16:23:0112732TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312733 class FakeUploadElementReader : public UploadElementReader {
12734 public:
Chris Watkins7a41d3552017-12-01 02:13:2712735 FakeUploadElementReader() = default;
12736 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0312737
Matt Menkecc1d3a902018-02-05 18:27:3312738 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0312739
12740 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3312741 int Init(CompletionOnceCallback callback) override {
12742 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0312743 return ERR_IO_PENDING;
12744 }
avibf0746c2015-12-09 19:53:1412745 uint64_t GetContentLength() const override { return 0; }
12746 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2012747 int Read(IOBuffer* buf,
12748 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3312749 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0312750 return ERR_FAILED;
12751 }
12752
12753 private:
Matt Menkecc1d3a902018-02-05 18:27:3312754 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0312755 };
12756
12757 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0912758 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12759 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2212760 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0312761
12762 HttpRequestInfo request;
12763 request.method = "POST";
bncce36dca22015-04-21 22:11:2312764 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0312765 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012766 request.traffic_annotation =
12767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0312768
danakj1fd259a02016-04-16 03:17:0912769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812770 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912771 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0312772
12773 StaticSocketDataProvider data;
12774 session_deps_.socket_factory->AddSocketDataProvider(&data);
12775
12776 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2012777 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112778 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5512779 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0312780
12781 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3312782 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
12783 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0312784
12785 // Return Init()'s result after the transaction gets destroyed.
12786 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3312787 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0312788}
12789
[email protected]aeefc9e82010-02-19 16:18:2712790// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0112791TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2712792 HttpRequestInfo request;
12793 request.method = "GET";
bncce36dca22015-04-21 22:11:2312794 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012795 request.traffic_annotation =
12796 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2712797
12798 // First transaction will request a resource and receive a Basic challenge
12799 // with realm="first_realm".
12800 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312801 MockWrite(
12802 "GET / HTTP/1.1\r\n"
12803 "Host: www.example.org\r\n"
12804 "Connection: keep-alive\r\n"
12805 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712806 };
12807 MockRead data_reads1[] = {
12808 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12809 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12810 "\r\n"),
12811 };
12812
bnc691fda62016-08-12 00:43:1612813 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2712814 // for first_realm. The server will reject and provide a challenge with
12815 // second_realm.
12816 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312817 MockWrite(
12818 "GET / HTTP/1.1\r\n"
12819 "Host: www.example.org\r\n"
12820 "Connection: keep-alive\r\n"
12821 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
12822 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712823 };
12824 MockRead data_reads2[] = {
12825 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12826 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
12827 "\r\n"),
12828 };
12829
12830 // This again fails, and goes back to first_realm. Make sure that the
12831 // entry is removed from cache.
12832 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2312833 MockWrite(
12834 "GET / HTTP/1.1\r\n"
12835 "Host: www.example.org\r\n"
12836 "Connection: keep-alive\r\n"
12837 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
12838 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712839 };
12840 MockRead data_reads3[] = {
12841 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12842 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12843 "\r\n"),
12844 };
12845
12846 // Try one last time (with the correct password) and get the resource.
12847 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312848 MockWrite(
12849 "GET / HTTP/1.1\r\n"
12850 "Host: www.example.org\r\n"
12851 "Connection: keep-alive\r\n"
12852 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12853 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712854 };
12855 MockRead data_reads4[] = {
12856 MockRead("HTTP/1.1 200 OK\r\n"
12857 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012858 "Content-Length: 5\r\n"
12859 "\r\n"
12860 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712861 };
12862
Ryan Sleevib8d7ea02018-05-07 20:01:0112863 StaticSocketDataProvider data1(data_reads1, data_writes1);
12864 StaticSocketDataProvider data2(data_reads2, data_writes2);
12865 StaticSocketDataProvider data3(data_reads3, data_writes3);
12866 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712867 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12868 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12869 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12870 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712871
[email protected]49639fa2011-12-20 23:22:4112872 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712873
danakj1fd259a02016-04-16 03:17:0912874 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612875 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012876
[email protected]aeefc9e82010-02-19 16:18:2712877 // Issue the first request with Authorize headers. There should be a
12878 // password prompt for first_realm waiting to be filled in after the
12879 // transaction completes.
tfarina42834112016-09-22 13:38:2012880 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112881 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712882 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112883 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612884 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212885 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812886 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212887 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412888 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312889 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412890 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912891 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712892
12893 // Issue the second request with an incorrect password. There should be a
12894 // password prompt for second_realm waiting to be filled in after the
12895 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112896 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612897 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12898 callback2.callback());
robpercival214763f2016-07-01 23:27:0112899 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712900 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112901 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612902 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212903 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812904 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212905 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412906 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312907 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412908 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912909 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712910
12911 // Issue the third request with another incorrect password. There should be
12912 // a password prompt for first_realm waiting to be filled in. If the password
12913 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12914 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112915 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612916 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12917 callback3.callback());
robpercival214763f2016-07-01 23:27:0112918 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712919 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112920 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612921 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212922 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812923 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212924 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412925 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312926 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412927 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912928 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712929
12930 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112931 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612932 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12933 callback4.callback());
robpercival214763f2016-07-01 23:27:0112934 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712935 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112936 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612937 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212938 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812939 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712940}
12941
Bence Béky230ac612017-08-30 19:17:0812942// Regression test for https://crbug.com/754395.
12943TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12944 MockRead data_reads[] = {
12945 MockRead("HTTP/1.1 200 OK\r\n"),
12946 MockRead(kAlternativeServiceHttpHeader),
12947 MockRead("\r\n"),
12948 MockRead("hello world"),
12949 MockRead(SYNCHRONOUS, OK),
12950 };
12951
12952 HttpRequestInfo request;
12953 request.method = "GET";
12954 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012955 request.traffic_annotation =
12956 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812957
Ryan Sleevib8d7ea02018-05-07 20:01:0112958 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812959 session_deps_.socket_factory->AddSocketDataProvider(&data);
12960
12961 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912962 ssl.ssl_info.cert =
12963 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12964 ASSERT_TRUE(ssl.ssl_info.cert);
12965 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812966 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12967
12968 TestCompletionCallback callback;
12969
12970 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12971 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12972
12973 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12974 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12975
12976 url::SchemeHostPort test_server(request.url);
12977 HttpServerProperties* http_server_properties =
12978 session->http_server_properties();
12979 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912980 http_server_properties
12981 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12982 .empty());
Bence Béky230ac612017-08-30 19:17:0812983
12984 EXPECT_THAT(callback.WaitForResult(), IsOk());
12985
12986 const HttpResponseInfo* response = trans.GetResponseInfo();
12987 ASSERT_TRUE(response);
12988 ASSERT_TRUE(response->headers);
12989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12990 EXPECT_FALSE(response->was_fetched_via_spdy);
12991 EXPECT_FALSE(response->was_alpn_negotiated);
12992
12993 std::string response_data;
12994 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12995 EXPECT_EQ("hello world", response_data);
12996
12997 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912998 http_server_properties
12999 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13000 .empty());
Bence Béky230ac612017-08-30 19:17:0813001}
13002
bncd16676a2016-07-20 16:23:0113003TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5213004 MockRead data_reads[] = {
13005 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313006 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213007 MockRead("\r\n"),
13008 MockRead("hello world"),
13009 MockRead(SYNCHRONOUS, OK),
13010 };
13011
13012 HttpRequestInfo request;
13013 request.method = "GET";
bncb26024382016-06-29 02:39:4513014 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013015 request.traffic_annotation =
13016 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213017
Ryan Sleevib8d7ea02018-05-07 20:01:0113018 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213019 session_deps_.socket_factory->AddSocketDataProvider(&data);
13020
bncb26024382016-06-29 02:39:4513021 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913022 ssl.ssl_info.cert =
13023 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13024 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13026
bncc958faa2015-07-31 18:14:5213027 TestCompletionCallback callback;
13028
danakj1fd259a02016-04-16 03:17:0913029 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613030 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213031
tfarina42834112016-09-22 13:38:2013032 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113033 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213034
bncb26024382016-06-29 02:39:4513035 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013036 HttpServerProperties* http_server_properties =
13037 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413038 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913039 http_server_properties
13040 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13041 .empty());
bncc958faa2015-07-31 18:14:5213042
robpercival214763f2016-07-01 23:27:0113043 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213044
bnc691fda62016-08-12 00:43:1613045 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213046 ASSERT_TRUE(response);
13047 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213048 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13049 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213050 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213051
13052 std::string response_data;
bnc691fda62016-08-12 00:43:1613053 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213054 EXPECT_EQ("hello world", response_data);
13055
zhongyic4de03032017-05-19 04:07:3413056 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913057 http_server_properties->GetAlternativeServiceInfos(test_server,
13058 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413059 ASSERT_EQ(1u, alternative_service_info_vector.size());
13060 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13061 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413062 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5213063}
13064
Matt Menke3233d8f22019-08-20 21:01:4913065TEST_F(HttpNetworkTransactionTest,
13066 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
13067 base::test::ScopedFeatureList feature_list;
13068 feature_list.InitWithFeatures(
13069 // enabled_features
13070 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
13071 // Need to partition connections by NetworkIsolationKey for
13072 // SpdySessionKeys to include NetworkIsolationKeys.
13073 features::kPartitionConnectionsByNetworkIsolationKey},
13074 // disabled_features
13075 {});
13076 // Since HttpServerProperties caches the feature value, have to create a new
13077 // one.
13078 session_deps_.http_server_properties =
13079 std::make_unique<HttpServerProperties>();
13080
13081 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
13082 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
13083 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
13084 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
13085
13086 MockRead data_reads[] = {
13087 MockRead("HTTP/1.1 200 OK\r\n"),
13088 MockRead(kAlternativeServiceHttpHeader),
13089 MockRead("\r\n"),
13090 MockRead("hello world"),
13091 MockRead(SYNCHRONOUS, OK),
13092 };
13093
13094 HttpRequestInfo request;
13095 request.method = "GET";
13096 request.url = GURL("https://www.example.org/");
13097 request.traffic_annotation =
13098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13099 request.network_isolation_key = kNetworkIsolationKey1;
13100
13101 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
13102 session_deps_.socket_factory->AddSocketDataProvider(&data);
13103
13104 SSLSocketDataProvider ssl(ASYNC, OK);
13105 ssl.ssl_info.cert =
13106 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13107 ASSERT_TRUE(ssl.ssl_info.cert);
13108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13109
13110 TestCompletionCallback callback;
13111
13112 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13113 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13114
13115 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13117
13118 url::SchemeHostPort test_server(request.url);
13119 HttpServerProperties* http_server_properties =
13120 session->http_server_properties();
13121 EXPECT_TRUE(
13122 http_server_properties
13123 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
13124 .empty());
13125
13126 EXPECT_THAT(callback.WaitForResult(), IsOk());
13127
13128 const HttpResponseInfo* response = trans.GetResponseInfo();
13129 ASSERT_TRUE(response);
13130 ASSERT_TRUE(response->headers);
13131 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13132 EXPECT_FALSE(response->was_fetched_via_spdy);
13133 EXPECT_FALSE(response->was_alpn_negotiated);
13134
13135 std::string response_data;
13136 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13137 EXPECT_EQ("hello world", response_data);
13138
13139 AlternativeServiceInfoVector alternative_service_info_vector =
13140 http_server_properties->GetAlternativeServiceInfos(test_server,
13141 kNetworkIsolationKey1);
13142 ASSERT_EQ(1u, alternative_service_info_vector.size());
13143 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13144 EXPECT_EQ(alternative_service,
13145 alternative_service_info_vector[0].alternative_service());
13146
13147 // Make sure the alternative service information is only associated with
13148 // kNetworkIsolationKey1.
13149 EXPECT_TRUE(
13150 http_server_properties
13151 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13152 .empty());
13153 EXPECT_TRUE(
13154 http_server_properties
13155 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13156 .empty());
13157}
13158
bnce3dd56f2016-06-01 10:37:1113159// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113160TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113161 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113162 MockRead data_reads[] = {
13163 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313164 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113165 MockRead("\r\n"),
13166 MockRead("hello world"),
13167 MockRead(SYNCHRONOUS, OK),
13168 };
13169
13170 HttpRequestInfo request;
13171 request.method = "GET";
13172 request.url = GURL("http://www.example.org/");
13173 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013174 request.traffic_annotation =
13175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113176
Ryan Sleevib8d7ea02018-05-07 20:01:0113177 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113178 session_deps_.socket_factory->AddSocketDataProvider(&data);
13179
13180 TestCompletionCallback callback;
13181
13182 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613183 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113184
13185 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013186 HttpServerProperties* http_server_properties =
13187 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413188 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913189 http_server_properties
13190 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13191 .empty());
bnce3dd56f2016-06-01 10:37:1113192
tfarina42834112016-09-22 13:38:2013193 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13195 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113196
bnc691fda62016-08-12 00:43:1613197 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113198 ASSERT_TRUE(response);
13199 ASSERT_TRUE(response->headers);
13200 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13201 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213202 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113203
13204 std::string response_data;
bnc691fda62016-08-12 00:43:1613205 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113206 EXPECT_EQ("hello world", response_data);
13207
zhongyic4de03032017-05-19 04:07:3413208 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913209 http_server_properties
13210 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13211 .empty());
bnce3dd56f2016-06-01 10:37:1113212}
13213
bnca86731e2017-04-17 12:31:2813214// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513215// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113216TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513217 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813218 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513219
bnc8bef8da22016-05-30 01:28:2513220 HttpRequestInfo request;
13221 request.method = "GET";
bncb26024382016-06-29 02:39:4513222 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513223 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013224 request.traffic_annotation =
13225 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513226
13227 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13228 StaticSocketDataProvider first_data;
13229 first_data.set_connect_data(mock_connect);
13230 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513231 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613232 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513233 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513234
13235 MockRead data_reads[] = {
13236 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13237 MockRead(ASYNC, OK),
13238 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113239 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513240 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13241
13242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13243
bnc525e175a2016-06-20 12:36:4013244 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513245 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113246 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13247 444);
bnc8bef8da22016-05-30 01:28:2513248 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113249 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713250 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13251 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513252
bnc691fda62016-08-12 00:43:1613253 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513254 TestCompletionCallback callback;
13255
tfarina42834112016-09-22 13:38:2013256 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513257 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113258 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513259}
13260
bnce3dd56f2016-06-01 10:37:1113261// Regression test for https://crbug.com/615497:
13262// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113263TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113264 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113265 HttpRequestInfo request;
13266 request.method = "GET";
13267 request.url = GURL("http://www.example.org/");
13268 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013269 request.traffic_annotation =
13270 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113271
13272 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13273 StaticSocketDataProvider first_data;
13274 first_data.set_connect_data(mock_connect);
13275 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13276
13277 MockRead data_reads[] = {
13278 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13279 MockRead(ASYNC, OK),
13280 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113281 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113282 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13283
13284 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13285
bnc525e175a2016-06-20 12:36:4013286 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113287 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113288 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113289 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113290 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713291 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13292 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113293
bnc691fda62016-08-12 00:43:1613294 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113295 TestCompletionCallback callback;
13296
tfarina42834112016-09-22 13:38:2013297 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113298 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113299 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113300}
13301
bncd16676a2016-07-20 16:23:0113302TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813303 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013305 HttpServerProperties* http_server_properties =
13306 session->http_server_properties();
bncb26024382016-06-29 02:39:4513307 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113308 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813309 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113310 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713311 test_server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813312 session->context().quic_context->params()->supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913313 EXPECT_EQ(1u,
13314 http_server_properties
13315 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13316 .size());
bnc4f575852015-10-14 18:35:0813317
13318 // Send a clear header.
13319 MockRead data_reads[] = {
13320 MockRead("HTTP/1.1 200 OK\r\n"),
13321 MockRead("Alt-Svc: clear\r\n"),
13322 MockRead("\r\n"),
13323 MockRead("hello world"),
13324 MockRead(SYNCHRONOUS, OK),
13325 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113326 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813327 session_deps_.socket_factory->AddSocketDataProvider(&data);
13328
bncb26024382016-06-29 02:39:4513329 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913330 ssl.ssl_info.cert =
13331 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13332 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13334
bnc4f575852015-10-14 18:35:0813335 HttpRequestInfo request;
13336 request.method = "GET";
bncb26024382016-06-29 02:39:4513337 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013338 request.traffic_annotation =
13339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813340
13341 TestCompletionCallback callback;
13342
bnc691fda62016-08-12 00:43:1613343 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813344
tfarina42834112016-09-22 13:38:2013345 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113346 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813347
bnc691fda62016-08-12 00:43:1613348 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213349 ASSERT_TRUE(response);
13350 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813351 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13352 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213353 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813354
13355 std::string response_data;
bnc691fda62016-08-12 00:43:1613356 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813357 EXPECT_EQ("hello world", response_data);
13358
zhongyic4de03032017-05-19 04:07:3413359 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913360 http_server_properties
13361 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13362 .empty());
bnc4f575852015-10-14 18:35:0813363}
13364
bncd16676a2016-07-20 16:23:0113365TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213366 MockRead data_reads[] = {
13367 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313368 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13369 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213370 MockRead("hello world"),
13371 MockRead(SYNCHRONOUS, OK),
13372 };
13373
13374 HttpRequestInfo request;
13375 request.method = "GET";
bncb26024382016-06-29 02:39:4513376 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013377 request.traffic_annotation =
13378 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213379
Ryan Sleevib8d7ea02018-05-07 20:01:0113380 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213381 session_deps_.socket_factory->AddSocketDataProvider(&data);
13382
bncb26024382016-06-29 02:39:4513383 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913384 ssl.ssl_info.cert =
13385 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13386 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513387 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13388
bncc958faa2015-07-31 18:14:5213389 TestCompletionCallback callback;
13390
danakj1fd259a02016-04-16 03:17:0913391 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613392 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213393
tfarina42834112016-09-22 13:38:2013394 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213396
bncb26024382016-06-29 02:39:4513397 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013398 HttpServerProperties* http_server_properties =
13399 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413400 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913401 http_server_properties
13402 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13403 .empty());
bncc958faa2015-07-31 18:14:5213404
robpercival214763f2016-07-01 23:27:0113405 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213406
bnc691fda62016-08-12 00:43:1613407 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213408 ASSERT_TRUE(response);
13409 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213410 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13411 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213412 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213413
13414 std::string response_data;
bnc691fda62016-08-12 00:43:1613415 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213416 EXPECT_EQ("hello world", response_data);
13417
zhongyic4de03032017-05-19 04:07:3413418 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913419 http_server_properties->GetAlternativeServiceInfos(test_server,
13420 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413421 ASSERT_EQ(2u, alternative_service_info_vector.size());
13422
13423 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13424 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413425 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413426 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13427 1234);
13428 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413429 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213430}
13431
bncd16676a2016-07-20 16:23:0113432TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613433 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213434 HostPortPair alternative("alternative.example.org", 443);
13435 std::string origin_url = "https://origin.example.org:443";
13436 std::string alternative_url = "https://alternative.example.org:443";
13437
13438 // Negotiate HTTP/1.1 with alternative.example.org.
13439 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613440 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13442
13443 // HTTP/1.1 data for request.
13444 MockWrite http_writes[] = {
13445 MockWrite("GET / HTTP/1.1\r\n"
13446 "Host: alternative.example.org\r\n"
13447 "Connection: keep-alive\r\n\r\n"),
13448 };
13449
13450 MockRead http_reads[] = {
13451 MockRead("HTTP/1.1 200 OK\r\n"
13452 "Content-Type: text/html; charset=iso-8859-1\r\n"
13453 "Content-Length: 40\r\n\r\n"
13454 "first HTTP/1.1 response from alternative"),
13455 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113456 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213457 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13458
13459 StaticSocketDataProvider data_refused;
13460 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13461 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13462
zhongyi3d4a55e72016-04-22 20:36:4613463 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913464 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013465 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213466 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113467 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213468 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113469 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713470 server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813471 DefaultSupportedQuicVersions());
zhongyi48704c182015-12-07 07:52:0213472 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513473 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13474 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213475
zhongyi48704c182015-12-07 07:52:0213476 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613477 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213478 request.method = "GET";
13479 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013480 request.traffic_annotation =
13481 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13482
zhongyi48704c182015-12-07 07:52:0213483 TestCompletionCallback callback;
13484 NetErrorDetails details;
13485 EXPECT_FALSE(details.quic_broken);
13486
tfarina42834112016-09-22 13:38:2013487 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613488 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213489 EXPECT_TRUE(details.quic_broken);
13490}
13491
bncd16676a2016-07-20 16:23:0113492TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613493 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213494 HostPortPair alternative1("alternative1.example.org", 443);
13495 HostPortPair alternative2("alternative2.example.org", 443);
13496 std::string origin_url = "https://origin.example.org:443";
13497 std::string alternative_url1 = "https://alternative1.example.org:443";
13498 std::string alternative_url2 = "https://alternative2.example.org:443";
13499
13500 // Negotiate HTTP/1.1 with alternative1.example.org.
13501 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613502 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13504
13505 // HTTP/1.1 data for request.
13506 MockWrite http_writes[] = {
13507 MockWrite("GET / HTTP/1.1\r\n"
13508 "Host: alternative1.example.org\r\n"
13509 "Connection: keep-alive\r\n\r\n"),
13510 };
13511
13512 MockRead http_reads[] = {
13513 MockRead("HTTP/1.1 200 OK\r\n"
13514 "Content-Type: text/html; charset=iso-8859-1\r\n"
13515 "Content-Length: 40\r\n\r\n"
13516 "first HTTP/1.1 response from alternative1"),
13517 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113518 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213519 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13520
13521 StaticSocketDataProvider data_refused;
13522 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13523 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13524
danakj1fd259a02016-04-16 03:17:0913525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013526 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213527 session->http_server_properties();
13528
zhongyi3d4a55e72016-04-22 20:36:4613529 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213530 AlternativeServiceInfoVector alternative_service_info_vector;
13531 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13532
bnc3472afd2016-11-17 15:27:2113533 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113534 alternative_service_info_vector.push_back(
13535 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13536 alternative_service1, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813537 session->context().quic_context->params()->supported_versions));
bnc3472afd2016-11-17 15:27:2113538 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113539 alternative_service_info_vector.push_back(
13540 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13541 alternative_service2, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813542 session->context().quic_context->params()->supported_versions));
zhongyi48704c182015-12-07 07:52:0213543
13544 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913545 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213546
13547 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513548 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13549 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913550 EXPECT_EQ(2u, http_server_properties
13551 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13552 .size());
zhongyi48704c182015-12-07 07:52:0213553
zhongyi48704c182015-12-07 07:52:0213554 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613555 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213556 request.method = "GET";
13557 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013558 request.traffic_annotation =
13559 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13560
zhongyi48704c182015-12-07 07:52:0213561 TestCompletionCallback callback;
13562 NetErrorDetails details;
13563 EXPECT_FALSE(details.quic_broken);
13564
tfarina42834112016-09-22 13:38:2013565 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613566 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213567 EXPECT_FALSE(details.quic_broken);
13568}
13569
bncd16676a2016-07-20 16:23:0113570TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213571 HttpRequestInfo request;
13572 request.method = "GET";
bncb26024382016-06-29 02:39:4513573 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013574 request.traffic_annotation =
13575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213576
[email protected]d973e99a2012-02-17 21:02:3613577 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213578 StaticSocketDataProvider first_data;
13579 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713580 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513581 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613582 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213584
13585 MockRead data_reads[] = {
13586 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13587 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613588 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213589 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113590 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713591 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213592
danakj1fd259a02016-04-16 03:17:0913593 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213594
bnc525e175a2016-06-20 12:36:4013595 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313596 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613597 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113598 // Port must be < 1024, or the header will be ignored (since initial port was
13599 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113600 // Port is ignored by MockConnect anyway.
13601 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13602 666);
bnc7dc7e1b42015-07-28 14:43:1213603 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113604 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713605 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213606
bnc691fda62016-08-12 00:43:1613607 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113608 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213609
tfarina42834112016-09-22 13:38:2013610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13612 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213613
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);
[email protected]564b4912010-03-09 16:30:4213617 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13618
13619 std::string response_data;
bnc691fda62016-08-12 00:43:1613620 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213621 EXPECT_EQ("hello world", response_data);
13622
zhongyic4de03032017-05-19 04:07:3413623 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913624 http_server_properties->GetAlternativeServiceInfos(server,
13625 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413626 ASSERT_EQ(1u, alternative_service_info_vector.size());
13627 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413628 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513629 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13630 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213631}
13632
bnc55ff9da2015-08-19 18:42:3513633// Ensure that we are not allowed to redirect traffic via an alternate protocol
13634// to an unrestricted (port >= 1024) when the original traffic was on a
13635// restricted port (port < 1024). Ensure that we can redirect in all other
13636// cases.
bncd16676a2016-07-20 16:23:0113637TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113638 HttpRequestInfo restricted_port_request;
13639 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513640 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113641 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013642 restricted_port_request.traffic_annotation =
13643 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113644
[email protected]d973e99a2012-02-17 21:02:3613645 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113646 StaticSocketDataProvider first_data;
13647 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713648 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113649
13650 MockRead data_reads[] = {
13651 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13652 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613653 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113654 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113655 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713656 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513657 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613658 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513659 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113660
danakj1fd259a02016-04-16 03:17:0913661 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113662
bnc525e175a2016-06-20 12:36:4013663 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313664 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113665 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113666 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13667 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213668 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113669 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713670 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13671 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113672
bnc691fda62016-08-12 00:43:1613673 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113674 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113675
tfarina42834112016-09-22 13:38:2013676 int rv = trans.Start(&restricted_port_request, callback.callback(),
13677 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113679 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113680 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913681}
[email protected]3912662a32011-10-04 00:51:1113682
bnc55ff9da2015-08-19 18:42:3513683// Ensure that we are allowed to redirect traffic via an alternate protocol to
13684// an unrestricted (port >= 1024) when the original traffic was on a restricted
13685// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113686TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713687 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913688
13689 HttpRequestInfo restricted_port_request;
13690 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513691 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913692 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013693 restricted_port_request.traffic_annotation =
13694 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913695
13696 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13697 StaticSocketDataProvider first_data;
13698 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713699 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913700
13701 MockRead data_reads[] = {
13702 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13703 MockRead("hello world"),
13704 MockRead(ASYNC, OK),
13705 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113706 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713707 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513708 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613709 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513710 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913711
danakj1fd259a02016-04-16 03:17:0913712 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913713
bnc525e175a2016-06-20 12:36:4013714 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913715 session->http_server_properties();
13716 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113717 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13718 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213719 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113720 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713721 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13722 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913723
bnc691fda62016-08-12 00:43:1613724 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913725 TestCompletionCallback callback;
13726
tfarina42834112016-09-22 13:38:2013727 EXPECT_EQ(ERR_IO_PENDING,
13728 trans.Start(&restricted_port_request, callback.callback(),
13729 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913730 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113731 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113732}
13733
bnc55ff9da2015-08-19 18:42:3513734// Ensure that we are not allowed to redirect traffic via an alternate protocol
13735// to an unrestricted (port >= 1024) when the original traffic was on a
13736// restricted port (port < 1024). Ensure that we can redirect in all other
13737// cases.
bncd16676a2016-07-20 16:23:0113738TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1113739 HttpRequestInfo restricted_port_request;
13740 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513741 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113742 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013743 restricted_port_request.traffic_annotation =
13744 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113745
[email protected]d973e99a2012-02-17 21:02:3613746 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113747 StaticSocketDataProvider first_data;
13748 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713749 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113750
13751 MockRead data_reads[] = {
13752 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13753 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613754 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113755 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113756 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713757 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113758
bncb26024382016-06-29 02:39:4513759 SSLSocketDataProvider ssl(ASYNC, OK);
13760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13761
danakj1fd259a02016-04-16 03:17:0913762 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113763
bnc525e175a2016-06-20 12:36:4013764 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313765 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113766 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113767 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13768 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213769 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113770 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713771 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13772 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113773
bnc691fda62016-08-12 00:43:1613774 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113775 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113776
tfarina42834112016-09-22 13:38:2013777 int rv = trans.Start(&restricted_port_request, callback.callback(),
13778 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113779 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113780 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113781 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113782}
13783
bnc55ff9da2015-08-19 18:42:3513784// Ensure that we are not allowed to redirect traffic via an alternate protocol
13785// to an unrestricted (port >= 1024) when the original traffic was on a
13786// restricted port (port < 1024). Ensure that we can redirect in all other
13787// cases.
bncd16676a2016-07-20 16:23:0113788TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1113789 HttpRequestInfo unrestricted_port_request;
13790 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513791 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113792 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013793 unrestricted_port_request.traffic_annotation =
13794 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113795
[email protected]d973e99a2012-02-17 21:02:3613796 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113797 StaticSocketDataProvider first_data;
13798 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713799 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113800
13801 MockRead data_reads[] = {
13802 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13803 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613804 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113805 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113806 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713807 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513808 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613809 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513810 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113811
danakj1fd259a02016-04-16 03:17:0913812 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113813
bnc525e175a2016-06-20 12:36:4013814 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313815 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113816 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113817 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13818 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213819 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113820 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713821 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13822 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113823
bnc691fda62016-08-12 00:43:1613824 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113825 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113826
bnc691fda62016-08-12 00:43:1613827 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013828 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113829 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113830 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113831 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113832}
13833
bnc55ff9da2015-08-19 18:42:3513834// Ensure that we are not allowed to redirect traffic via an alternate protocol
13835// to an unrestricted (port >= 1024) when the original traffic was on a
13836// restricted port (port < 1024). Ensure that we can redirect in all other
13837// cases.
bncd16676a2016-07-20 16:23:0113838TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113839 HttpRequestInfo unrestricted_port_request;
13840 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513841 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113842 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013843 unrestricted_port_request.traffic_annotation =
13844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113845
[email protected]d973e99a2012-02-17 21:02:3613846 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113847 StaticSocketDataProvider first_data;
13848 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713849 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113850
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]3912662a32011-10-04 00:51:1113855 };
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]3912662a32011-10-04 00:51:1113858
bncb26024382016-06-29 02:39:4513859 SSLSocketDataProvider ssl(ASYNC, OK);
13860 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13861
danakj1fd259a02016-04-16 03:17:0913862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113863
bnc525e175a2016-06-20 12:36:4013864 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313865 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213866 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113867 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13868 kUnrestrictedAlternatePort);
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 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13872 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113873
bnc691fda62016-08-12 00:43:1613874 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113875 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113876
bnc691fda62016-08-12 00:43:1613877 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013878 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113880 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113881 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113882}
13883
bnc55ff9da2015-08-19 18:42:3513884// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113885// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13886// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113887TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213888 HttpRequestInfo request;
13889 request.method = "GET";
bncce36dca22015-04-21 22:11:2313890 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013891 request.traffic_annotation =
13892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213893
13894 // The alternate protocol request will error out before we attempt to connect,
13895 // so only the standard HTTP request will try to connect.
13896 MockRead data_reads[] = {
13897 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13898 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613899 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213900 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113901 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713902 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213903
danakj1fd259a02016-04-16 03:17:0913904 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213905
bnc525e175a2016-06-20 12:36:4013906 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213907 session->http_server_properties();
13908 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113909 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13910 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213911 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113912 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713913 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13914 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213915
bnc691fda62016-08-12 00:43:1613916 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213917 TestCompletionCallback callback;
13918
tfarina42834112016-09-22 13:38:2013919 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213921 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113922 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213923
bnc691fda62016-08-12 00:43:1613924 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213925 ASSERT_TRUE(response);
13926 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213927 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13928
13929 std::string response_data;
bnc691fda62016-08-12 00:43:1613930 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213931 EXPECT_EQ("hello world", response_data);
13932}
13933
bncd16676a2016-07-20 16:23:0113934TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413935 HttpRequestInfo request;
13936 request.method = "GET";
bncb26024382016-06-29 02:39:4513937 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013938 request.traffic_annotation =
13939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413940
13941 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213942 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313943 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213944 MockRead("\r\n"),
13945 MockRead("hello world"),
13946 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13947 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413948
Ryan Sleevib8d7ea02018-05-07 20:01:0113949 StaticSocketDataProvider first_transaction(data_reads,
13950 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713951 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513952 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613953 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513954 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413955
bnc032658ba2016-09-26 18:17:1513956 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413957
Ryan Hamilton0239aac2018-05-19 00:03:1313958 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513959 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113960 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413961
Raul Tambre94493c652019-03-11 17:18:3513962 spdy::SpdySerializedFrame resp(
13963 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313964 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413965 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113966 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413967 };
13968
Ryan Sleevib8d7ea02018-05-07 20:01:0113969 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713970 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413971
[email protected]d973e99a2012-02-17 21:02:3613972 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113973 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513974 hanging_non_alternate_protocol_socket.set_connect_data(
13975 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713976 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513977 &hanging_non_alternate_protocol_socket);
13978
[email protected]49639fa2011-12-20 23:22:4113979 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413980
danakj1fd259a02016-04-16 03:17:0913981 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813982 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913983 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413984
tfarina42834112016-09-22 13:38:2013985 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113986 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13987 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413988
13989 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213990 ASSERT_TRUE(response);
13991 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413992 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13993
13994 std::string response_data;
robpercival214763f2016-07-01 23:27:0113995 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413996 EXPECT_EQ("hello world", response_data);
13997
bnc87dcefc2017-05-25 12:47:5813998 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913999 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414000
tfarina42834112016-09-22 13:38:2014001 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114002 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14003 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414004
14005 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214006 ASSERT_TRUE(response);
14007 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214008 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314009 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214010 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414011
robpercival214763f2016-07-01 23:27:0114012 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414013 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5414014}
14015
bncd16676a2016-07-20 16:23:0114016TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5514017 HttpRequestInfo request;
14018 request.method = "GET";
bncb26024382016-06-29 02:39:4514019 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014020 request.traffic_annotation =
14021 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514022
bncb26024382016-06-29 02:39:4514023 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5514024 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214025 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314026 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214027 MockRead("\r\n"),
14028 MockRead("hello world"),
14029 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14030 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514031 };
14032
Ryan Sleevib8d7ea02018-05-07 20:01:0114033 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4514034 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5514035
bncb26024382016-06-29 02:39:4514036 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914037 ssl_http11.ssl_info.cert =
14038 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14039 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4514040 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
14041
14042 // Second transaction starts an alternative and a non-alternative Job.
14043 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3614044 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114045 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1814046 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1814047 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
14048
Ryan Sleevib8d7ea02018-05-07 20:01:0114049 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1814050 hanging_socket2.set_connect_data(never_finishing_connect);
14051 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5514052
bncb26024382016-06-29 02:39:4514053 // Third transaction starts an alternative and a non-alternative job.
14054 // The non-alternative job hangs, but the alternative one succeeds.
14055 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1314056 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4514057 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1314058 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4514059 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5514060 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4114061 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5514062 };
Raul Tambre94493c652019-03-11 17:18:3514063 spdy::SpdySerializedFrame resp1(
14064 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314065 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3514066 spdy::SpdySerializedFrame resp2(
14067 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1314068 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5514069 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114070 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
14071 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1314072 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5514073 };
14074
Ryan Sleevib8d7ea02018-05-07 20:01:0114075 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714076 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5514077
bnc032658ba2016-09-26 18:17:1514078 AddSSLSocketData();
bncb26024382016-06-29 02:39:4514079
Ryan Sleevib8d7ea02018-05-07 20:01:0114080 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1814081 hanging_socket3.set_connect_data(never_finishing_connect);
14082 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5514083
danakj1fd259a02016-04-16 03:17:0914084 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4114085 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5014086 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514087
tfarina42834112016-09-22 13:38:2014088 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14090 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514091
14092 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5214093 ASSERT_TRUE(response);
14094 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514095 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14096
14097 std::string response_data;
robpercival214763f2016-07-01 23:27:0114098 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514099 EXPECT_EQ("hello world", response_data);
14100
[email protected]49639fa2011-12-20 23:22:4114101 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5014102 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014103 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514105
[email protected]49639fa2011-12-20 23:22:4114106 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5014107 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014108 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114109 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514110
robpercival214763f2016-07-01 23:27:0114111 EXPECT_THAT(callback2.WaitForResult(), IsOk());
14112 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514113
14114 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5214115 ASSERT_TRUE(response);
14116 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214117 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514118 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214119 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114120 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514121 EXPECT_EQ("hello!", response_data);
14122
14123 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5214124 ASSERT_TRUE(response);
14125 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214126 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514127 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214128 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114129 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514130 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5514131}
14132
bncd16676a2016-07-20 16:23:0114133TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5314134 session_deps_.host_resolver->set_synchronous_mode(true);
14135
[email protected]2d6728692011-03-12 01:39:5514136 HttpRequestInfo request;
14137 request.method = "GET";
bncb26024382016-06-29 02:39:4514138 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014139 request.traffic_annotation =
14140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514141
14142 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214143 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314144 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214145 MockRead("\r\n"),
14146 MockRead("hello world"),
14147 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14148 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514149 };
14150
Ryan Sleevib8d7ea02018-05-07 20:01:0114151 StaticSocketDataProvider first_transaction(data_reads,
14152 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714153 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5514154
[email protected]8ddf8322012-02-23 18:08:0614155 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914156 ssl.ssl_info.cert =
14157 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14158 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514160
[email protected]d973e99a2012-02-17 21:02:3614161 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114162 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514163 hanging_alternate_protocol_socket.set_connect_data(
14164 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714165 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514166 &hanging_alternate_protocol_socket);
14167
bncb26024382016-06-29 02:39:4514168 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114169 StaticSocketDataProvider second_transaction(data_reads,
14170 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814171 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514173
[email protected]49639fa2011-12-20 23:22:4114174 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514175
danakj1fd259a02016-04-16 03:17:0914176 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814177 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914178 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514179
tfarina42834112016-09-22 13:38:2014180 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114181 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14182 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514183
14184 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214185 ASSERT_TRUE(response);
14186 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514187 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14188
14189 std::string response_data;
robpercival214763f2016-07-01 23:27:0114190 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514191 EXPECT_EQ("hello world", response_data);
14192
bnc87dcefc2017-05-25 12:47:5814193 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914194 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514195
tfarina42834112016-09-22 13:38:2014196 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114197 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14198 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514199
14200 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214201 ASSERT_TRUE(response);
14202 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514203 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14204 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214205 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514206
robpercival214763f2016-07-01 23:27:0114207 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514208 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514209}
14210
bnc2e884782016-08-11 19:45:1914211// Test that proxy is resolved using the origin url,
14212// regardless of the alternative server.
14213TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14214 // Configure proxy to bypass www.example.org, which is the origin URL.
14215 ProxyConfig proxy_config;
14216 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14217 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914218 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14219 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914220
14221 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914222 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914223 &capturing_proxy_resolver);
14224
Matt Muellerd9342e3a2019-11-26 01:41:1414225 RecordingTestNetLog net_log;
bnc2e884782016-08-11 19:45:1914226
Bence Béky53a5aef2018-03-29 21:54:1214227 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614228 std::make_unique<ConfiguredProxyResolutionService>(
Bence Béky53a5aef2018-03-29 21:54:1214229 std::move(proxy_config_service), std::move(proxy_resolver_factory),
14230 &net_log);
bnc2e884782016-08-11 19:45:1914231
14232 session_deps_.net_log = &net_log;
14233
14234 // Configure alternative service with a hostname that is not bypassed by the
14235 // proxy.
14236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14237 HttpServerProperties* http_server_properties =
14238 session->http_server_properties();
14239 url::SchemeHostPort server("https", "www.example.org", 443);
14240 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114241 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914242 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114243 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714244 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914245
14246 // Non-alternative job should hang.
14247 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114248 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914249 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14250 session_deps_.socket_factory->AddSocketDataProvider(
14251 &hanging_alternate_protocol_socket);
14252
bnc032658ba2016-09-26 18:17:1514253 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914254
14255 HttpRequestInfo request;
14256 request.method = "GET";
14257 request.url = GURL("https://www.example.org/");
14258 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014259 request.traffic_annotation =
14260 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914261
Ryan Hamilton0239aac2018-05-19 00:03:1314262 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914263 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14264
14265 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14266
Ryan Hamilton0239aac2018-05-19 00:03:1314267 spdy::SpdySerializedFrame resp(
14268 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14269 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914270 MockRead spdy_reads[] = {
14271 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14272 };
14273
Ryan Sleevib8d7ea02018-05-07 20:01:0114274 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914275 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14276
14277 TestCompletionCallback callback;
14278
14279 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14280
tfarina42834112016-09-22 13:38:2014281 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914282 EXPECT_THAT(callback.GetResult(rv), IsOk());
14283
14284 const HttpResponseInfo* response = trans.GetResponseInfo();
14285 ASSERT_TRUE(response);
14286 ASSERT_TRUE(response->headers);
14287 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14288 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214289 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914290
14291 std::string response_data;
14292 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14293 EXPECT_EQ("hello!", response_data);
14294
14295 // Origin host bypasses proxy, no resolution should have happened.
Matt Menke8045afd2019-11-14 20:31:1914296 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
bnc2e884782016-08-11 19:45:1914297}
14298
bncd16676a2016-07-20 16:23:0114299TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114300 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214301 proxy_config.set_auto_detect(true);
14302 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114303
sammc5dd160c2015-04-02 02:43:1314304 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914305 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614306 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4914307 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14308 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14309 std::make_unique<CapturingProxyResolverFactory>(
14310 &capturing_proxy_resolver),
14311 nullptr);
Matt Muellerd9342e3a2019-11-26 01:41:1414312 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714313 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114314
14315 HttpRequestInfo request;
14316 request.method = "GET";
bncb26024382016-06-29 02:39:4514317 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014318 request.traffic_annotation =
14319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114320
14321 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214322 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314323 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214324 MockRead("\r\n"),
14325 MockRead("hello world"),
14326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14327 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114328 };
14329
Ryan Sleevib8d7ea02018-05-07 20:01:0114330 StaticSocketDataProvider first_transaction(data_reads,
14331 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714332 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514333 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614334 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114336
bnc032658ba2016-09-26 18:17:1514337 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114338
Ryan Hamilton0239aac2018-05-19 00:03:1314339 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514340 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114341 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314342 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514343 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14344 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314345 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114346 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114347 };
14348
[email protected]d911f1b2010-05-05 22:39:4214349 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14350
Raul Tambre94493c652019-03-11 17:18:3514351 spdy::SpdySerializedFrame resp(
14352 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314353 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114354 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114355 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14356 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114357 };
14358
Ryan Sleevib8d7ea02018-05-07 20:01:0114359 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714360 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114361
[email protected]d973e99a2012-02-17 21:02:3614362 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114363 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514364 hanging_non_alternate_protocol_socket.set_connect_data(
14365 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714366 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514367 &hanging_non_alternate_protocol_socket);
14368
[email protected]49639fa2011-12-20 23:22:4114369 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114370
danakj1fd259a02016-04-16 03:17:0914371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814372 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914373 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114374
tfarina42834112016-09-22 13:38:2014375 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114376 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14377 EXPECT_THAT(callback.WaitForResult(), IsOk());
14378
14379 const HttpResponseInfo* response = trans->GetResponseInfo();
14380 ASSERT_TRUE(response);
14381 ASSERT_TRUE(response->headers);
14382 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14383 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214384 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114385
14386 std::string response_data;
14387 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14388 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114389
bnc87dcefc2017-05-25 12:47:5814390 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914391 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114392
tfarina42834112016-09-22 13:38:2014393 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114394 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14395 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114396
mmenkea2dcd3bf2016-08-16 21:49:4114397 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214398 ASSERT_TRUE(response);
14399 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214400 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314401 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214402 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114403
robpercival214763f2016-07-01 23:27:0114404 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114405 EXPECT_EQ("hello!", response_data);
Matt Menke8045afd2019-11-14 20:31:1914406 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
bncb26024382016-06-29 02:39:4514407 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914408 capturing_proxy_resolver.lookup_info()[0].url.spec());
bncce36dca22015-04-21 22:11:2314409 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914410 capturing_proxy_resolver.lookup_info()[1].url.spec());
[email protected]631f1322010-04-30 17:59:1114411
[email protected]029c83b62013-01-24 05:28:2014412 LoadTimingInfo load_timing_info;
14413 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14414 TestLoadTimingNotReusedWithPac(load_timing_info,
14415 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114416}
[email protected]631f1322010-04-30 17:59:1114417
bncd16676a2016-07-20 16:23:0114418TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814419 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414420 HttpRequestInfo request;
14421 request.method = "GET";
bncb26024382016-06-29 02:39:4514422 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014423 request.traffic_annotation =
14424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414425
14426 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214427 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314428 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214429 MockRead("\r\n"),
14430 MockRead("hello world"),
14431 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414432 };
14433
Ryan Sleevib8d7ea02018-05-07 20:01:0114434 StaticSocketDataProvider first_transaction(data_reads,
14435 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714436 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514437 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614438 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414440
bnc032658ba2016-09-26 18:17:1514441 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414442
Ryan Hamilton0239aac2018-05-19 00:03:1314443 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514444 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114445 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414446
Raul Tambre94493c652019-03-11 17:18:3514447 spdy::SpdySerializedFrame resp(
14448 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314449 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414450 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114451 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414452 };
14453
Ryan Sleevib8d7ea02018-05-07 20:01:0114454 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714455 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414456
[email protected]83039bb2011-12-09 18:43:5514457 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414458
danakj1fd259a02016-04-16 03:17:0914459 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414460
bnc87dcefc2017-05-25 12:47:5814461 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914462 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414463
tfarina42834112016-09-22 13:38:2014464 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114465 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14466 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414467
14468 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214469 ASSERT_TRUE(response);
14470 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414471 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14472
14473 std::string response_data;
robpercival214763f2016-07-01 23:27:0114474 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414475 EXPECT_EQ("hello world", response_data);
14476
14477 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514478 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014479 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114480 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414481 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14482 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714483 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214484 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814485
bnc87dcefc2017-05-25 12:47:5814486 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914487 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414488
tfarina42834112016-09-22 13:38:2014489 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114490 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14491 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414492
14493 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214494 ASSERT_TRUE(response);
14495 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214496 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314497 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214498 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414499
robpercival214763f2016-07-01 23:27:0114500 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414501 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214502}
14503
[email protected]044de0642010-06-17 10:42:1514504// GenerateAuthToken is a mighty big test.
14505// It tests all permutation of GenerateAuthToken behavior:
14506// - Synchronous and Asynchronous completion.
14507// - OK or error on completion.
14508// - Direct connection, non-authenticating proxy, and authenticating proxy.
14509// - HTTP or HTTPS backend (to include proxy tunneling).
14510// - Non-authenticating and authenticating backend.
14511//
[email protected]fe3b7dc2012-02-03 19:52:0914512// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514513// problems generating an auth token for an authenticating proxy, we don't
14514// need to test all permutations of the backend server).
14515//
14516// The test proceeds by going over each of the configuration cases, and
14517// potentially running up to three rounds in each of the tests. The TestConfig
14518// specifies both the configuration for the test as well as the expectations
14519// for the results.
bncd16676a2016-07-20 16:23:0114520TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014521 static const char kServer[] = "http://www.example.com";
14522 static const char kSecureServer[] = "https://www.example.com";
14523 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514524
14525 enum AuthTiming {
14526 AUTH_NONE,
14527 AUTH_SYNC,
14528 AUTH_ASYNC,
14529 };
14530
14531 const MockWrite kGet(
14532 "GET / HTTP/1.1\r\n"
14533 "Host: www.example.com\r\n"
14534 "Connection: keep-alive\r\n\r\n");
14535 const MockWrite kGetProxy(
14536 "GET http://www.example.com/ HTTP/1.1\r\n"
14537 "Host: www.example.com\r\n"
14538 "Proxy-Connection: keep-alive\r\n\r\n");
14539 const MockWrite kGetAuth(
14540 "GET / HTTP/1.1\r\n"
14541 "Host: www.example.com\r\n"
14542 "Connection: keep-alive\r\n"
14543 "Authorization: auth_token\r\n\r\n");
14544 const MockWrite kGetProxyAuth(
14545 "GET http://www.example.com/ HTTP/1.1\r\n"
14546 "Host: www.example.com\r\n"
14547 "Proxy-Connection: keep-alive\r\n"
14548 "Proxy-Authorization: auth_token\r\n\r\n");
14549 const MockWrite kGetAuthThroughProxy(
14550 "GET http://www.example.com/ HTTP/1.1\r\n"
14551 "Host: www.example.com\r\n"
14552 "Proxy-Connection: keep-alive\r\n"
14553 "Authorization: auth_token\r\n\r\n");
14554 const MockWrite kGetAuthWithProxyAuth(
14555 "GET http://www.example.com/ HTTP/1.1\r\n"
14556 "Host: www.example.com\r\n"
14557 "Proxy-Connection: keep-alive\r\n"
14558 "Proxy-Authorization: auth_token\r\n"
14559 "Authorization: auth_token\r\n\r\n");
14560 const MockWrite kConnect(
14561 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714562 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514563 "Proxy-Connection: keep-alive\r\n\r\n");
14564 const MockWrite kConnectProxyAuth(
14565 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714566 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514567 "Proxy-Connection: keep-alive\r\n"
14568 "Proxy-Authorization: auth_token\r\n\r\n");
14569
14570 const MockRead kSuccess(
14571 "HTTP/1.1 200 OK\r\n"
14572 "Content-Type: text/html; charset=iso-8859-1\r\n"
14573 "Content-Length: 3\r\n\r\n"
14574 "Yes");
14575 const MockRead kFailure(
14576 "Should not be called.");
14577 const MockRead kServerChallenge(
14578 "HTTP/1.1 401 Unauthorized\r\n"
14579 "WWW-Authenticate: Mock realm=server\r\n"
14580 "Content-Type: text/html; charset=iso-8859-1\r\n"
14581 "Content-Length: 14\r\n\r\n"
14582 "Unauthorized\r\n");
14583 const MockRead kProxyChallenge(
14584 "HTTP/1.1 407 Unauthorized\r\n"
14585 "Proxy-Authenticate: Mock realm=proxy\r\n"
14586 "Proxy-Connection: close\r\n"
14587 "Content-Type: text/html; charset=iso-8859-1\r\n"
14588 "Content-Length: 14\r\n\r\n"
14589 "Unauthorized\r\n");
14590 const MockRead kProxyConnected(
14591 "HTTP/1.1 200 Connection Established\r\n\r\n");
14592
14593 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14594 // no constructors, but the C++ compiler on Windows warns about
14595 // unspecified data in compound literals. So, moved to using constructors,
14596 // and TestRound's created with the default constructor should not be used.
14597 struct TestRound {
14598 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514599 : expected_rv(ERR_UNEXPECTED),
14600 extra_write(nullptr),
14601 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314602 TestRound(const MockWrite& write_arg,
14603 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514604 int expected_rv_arg)
14605 : write(write_arg),
14606 read(read_arg),
14607 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514608 extra_write(nullptr),
14609 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514610 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14611 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114612 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514613 : write(write_arg),
14614 read(read_arg),
14615 expected_rv(expected_rv_arg),
14616 extra_write(extra_write_arg),
14617 extra_read(extra_read_arg) {
14618 }
14619 MockWrite write;
14620 MockRead read;
14621 int expected_rv;
14622 const MockWrite* extra_write;
14623 const MockRead* extra_read;
14624 };
14625
14626 static const int kNoSSL = 500;
14627
14628 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114629 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114630 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514631 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114632 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114633 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514634 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114635 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514636 int num_auth_rounds;
14637 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614638 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514639 } test_configs[] = {
asankac93076192016-10-03 15:46:0214640 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114641 {__LINE__,
14642 nullptr,
asankac93076192016-10-03 15:46:0214643 AUTH_NONE,
14644 OK,
14645 kServer,
14646 AUTH_NONE,
14647 OK,
14648 1,
14649 kNoSSL,
14650 {TestRound(kGet, kSuccess, OK)}},
14651 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114652 {__LINE__,
14653 nullptr,
asankac93076192016-10-03 15:46:0214654 AUTH_NONE,
14655 OK,
14656 kServer,
14657 AUTH_SYNC,
14658 OK,
14659 2,
14660 kNoSSL,
14661 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514662 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114663 {__LINE__,
14664 nullptr,
asankac93076192016-10-03 15:46:0214665 AUTH_NONE,
14666 OK,
14667 kServer,
14668 AUTH_SYNC,
14669 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614670 3,
14671 kNoSSL,
14672 {TestRound(kGet, kServerChallenge, OK),
14673 TestRound(kGet, kServerChallenge, OK),
14674 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114675 {__LINE__,
14676 nullptr,
asankae2257db2016-10-11 22:03:1614677 AUTH_NONE,
14678 OK,
14679 kServer,
14680 AUTH_SYNC,
14681 ERR_UNSUPPORTED_AUTH_SCHEME,
14682 2,
14683 kNoSSL,
14684 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114685 {__LINE__,
14686 nullptr,
asankae2257db2016-10-11 22:03:1614687 AUTH_NONE,
14688 OK,
14689 kServer,
14690 AUTH_SYNC,
14691 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14692 2,
14693 kNoSSL,
14694 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114695 {__LINE__,
14696 kProxy,
asankae2257db2016-10-11 22:03:1614697 AUTH_SYNC,
14698 ERR_FAILED,
14699 kServer,
14700 AUTH_NONE,
14701 OK,
14702 2,
14703 kNoSSL,
14704 {TestRound(kGetProxy, kProxyChallenge, OK),
14705 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114706 {__LINE__,
14707 kProxy,
asankae2257db2016-10-11 22:03:1614708 AUTH_ASYNC,
14709 ERR_FAILED,
14710 kServer,
14711 AUTH_NONE,
14712 OK,
14713 2,
14714 kNoSSL,
14715 {TestRound(kGetProxy, kProxyChallenge, OK),
14716 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114717 {__LINE__,
14718 nullptr,
asankae2257db2016-10-11 22:03:1614719 AUTH_NONE,
14720 OK,
14721 kServer,
14722 AUTH_SYNC,
14723 ERR_FAILED,
asankac93076192016-10-03 15:46:0214724 2,
14725 kNoSSL,
14726 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614727 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114728 {__LINE__,
14729 nullptr,
asankae2257db2016-10-11 22:03:1614730 AUTH_NONE,
14731 OK,
14732 kServer,
14733 AUTH_ASYNC,
14734 ERR_FAILED,
14735 2,
14736 kNoSSL,
14737 {TestRound(kGet, kServerChallenge, OK),
14738 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114739 {__LINE__,
14740 nullptr,
asankac93076192016-10-03 15:46:0214741 AUTH_NONE,
14742 OK,
14743 kServer,
14744 AUTH_ASYNC,
14745 OK,
14746 2,
14747 kNoSSL,
14748 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514749 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114750 {__LINE__,
14751 nullptr,
asankac93076192016-10-03 15:46:0214752 AUTH_NONE,
14753 OK,
14754 kServer,
14755 AUTH_ASYNC,
14756 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614757 3,
asankac93076192016-10-03 15:46:0214758 kNoSSL,
14759 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614760 // The second round uses a HttpAuthHandlerMock that always succeeds.
14761 TestRound(kGet, kServerChallenge, OK),
14762 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214763 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114764 {__LINE__,
14765 kProxy,
asankac93076192016-10-03 15:46:0214766 AUTH_NONE,
14767 OK,
14768 kServer,
14769 AUTH_NONE,
14770 OK,
14771 1,
14772 kNoSSL,
14773 {TestRound(kGetProxy, kSuccess, OK)}},
14774 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114775 {__LINE__,
14776 kProxy,
asankac93076192016-10-03 15:46:0214777 AUTH_NONE,
14778 OK,
14779 kServer,
14780 AUTH_SYNC,
14781 OK,
14782 2,
14783 kNoSSL,
14784 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514785 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114786 {__LINE__,
14787 kProxy,
asankac93076192016-10-03 15:46:0214788 AUTH_NONE,
14789 OK,
14790 kServer,
14791 AUTH_SYNC,
14792 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614793 3,
asankac93076192016-10-03 15:46:0214794 kNoSSL,
14795 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614796 TestRound(kGetProxy, kServerChallenge, OK),
14797 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114798 {__LINE__,
14799 kProxy,
asankac93076192016-10-03 15:46:0214800 AUTH_NONE,
14801 OK,
14802 kServer,
14803 AUTH_ASYNC,
14804 OK,
14805 2,
14806 kNoSSL,
14807 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514808 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114809 {__LINE__,
14810 kProxy,
asankac93076192016-10-03 15:46:0214811 AUTH_NONE,
14812 OK,
14813 kServer,
14814 AUTH_ASYNC,
14815 ERR_INVALID_AUTH_CREDENTIALS,
14816 2,
14817 kNoSSL,
14818 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614819 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214820 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114821 {__LINE__,
14822 kProxy,
asankac93076192016-10-03 15:46:0214823 AUTH_SYNC,
14824 OK,
14825 kServer,
14826 AUTH_NONE,
14827 OK,
14828 2,
14829 kNoSSL,
14830 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514831 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114832 {__LINE__,
14833 kProxy,
asankac93076192016-10-03 15:46:0214834 AUTH_SYNC,
14835 ERR_INVALID_AUTH_CREDENTIALS,
14836 kServer,
14837 AUTH_NONE,
14838 OK,
14839 2,
14840 kNoSSL,
14841 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614842 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114843 {__LINE__,
14844 kProxy,
asankac93076192016-10-03 15:46:0214845 AUTH_ASYNC,
14846 OK,
14847 kServer,
14848 AUTH_NONE,
14849 OK,
14850 2,
14851 kNoSSL,
14852 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514853 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114854 {__LINE__,
14855 kProxy,
asankac93076192016-10-03 15:46:0214856 AUTH_ASYNC,
14857 ERR_INVALID_AUTH_CREDENTIALS,
14858 kServer,
14859 AUTH_NONE,
14860 OK,
14861 2,
14862 kNoSSL,
14863 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614864 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114865 {__LINE__,
14866 kProxy,
14867 AUTH_ASYNC,
14868 ERR_INVALID_AUTH_CREDENTIALS,
14869 kServer,
14870 AUTH_NONE,
14871 OK,
14872 3,
14873 kNoSSL,
14874 {TestRound(kGetProxy, kProxyChallenge, OK),
14875 TestRound(kGetProxy, kProxyChallenge, OK),
14876 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214877 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114878 {__LINE__,
14879 kProxy,
asankac93076192016-10-03 15:46:0214880 AUTH_SYNC,
14881 OK,
14882 kServer,
14883 AUTH_SYNC,
14884 OK,
14885 3,
14886 kNoSSL,
14887 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514888 TestRound(kGetProxyAuth, kServerChallenge, OK),
14889 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114890 {__LINE__,
14891 kProxy,
asankac93076192016-10-03 15:46:0214892 AUTH_SYNC,
14893 OK,
14894 kServer,
14895 AUTH_SYNC,
14896 ERR_INVALID_AUTH_CREDENTIALS,
14897 3,
14898 kNoSSL,
14899 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514900 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614901 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114902 {__LINE__,
14903 kProxy,
asankac93076192016-10-03 15:46:0214904 AUTH_ASYNC,
14905 OK,
14906 kServer,
14907 AUTH_SYNC,
14908 OK,
14909 3,
14910 kNoSSL,
14911 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514912 TestRound(kGetProxyAuth, kServerChallenge, OK),
14913 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114914 {__LINE__,
14915 kProxy,
asankac93076192016-10-03 15:46:0214916 AUTH_ASYNC,
14917 OK,
14918 kServer,
14919 AUTH_SYNC,
14920 ERR_INVALID_AUTH_CREDENTIALS,
14921 3,
14922 kNoSSL,
14923 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514924 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614925 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114926 {__LINE__,
14927 kProxy,
asankac93076192016-10-03 15:46:0214928 AUTH_SYNC,
14929 OK,
14930 kServer,
14931 AUTH_ASYNC,
14932 OK,
14933 3,
14934 kNoSSL,
14935 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514936 TestRound(kGetProxyAuth, kServerChallenge, OK),
14937 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114938 {__LINE__,
14939 kProxy,
14940 AUTH_SYNC,
14941 ERR_INVALID_AUTH_CREDENTIALS,
14942 kServer,
14943 AUTH_ASYNC,
14944 OK,
14945 4,
14946 kNoSSL,
14947 {TestRound(kGetProxy, kProxyChallenge, OK),
14948 TestRound(kGetProxy, kProxyChallenge, OK),
14949 TestRound(kGetProxyAuth, kServerChallenge, OK),
14950 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14951 {__LINE__,
14952 kProxy,
asankac93076192016-10-03 15:46:0214953 AUTH_SYNC,
14954 OK,
14955 kServer,
14956 AUTH_ASYNC,
14957 ERR_INVALID_AUTH_CREDENTIALS,
14958 3,
14959 kNoSSL,
14960 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514961 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614962 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114963 {__LINE__,
14964 kProxy,
asankac93076192016-10-03 15:46:0214965 AUTH_ASYNC,
14966 OK,
14967 kServer,
14968 AUTH_ASYNC,
14969 OK,
14970 3,
14971 kNoSSL,
14972 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514973 TestRound(kGetProxyAuth, kServerChallenge, OK),
14974 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114975 {__LINE__,
14976 kProxy,
asankac93076192016-10-03 15:46:0214977 AUTH_ASYNC,
14978 OK,
14979 kServer,
14980 AUTH_ASYNC,
14981 ERR_INVALID_AUTH_CREDENTIALS,
14982 3,
14983 kNoSSL,
14984 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514985 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614986 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114987 {__LINE__,
14988 kProxy,
14989 AUTH_ASYNC,
14990 ERR_INVALID_AUTH_CREDENTIALS,
14991 kServer,
14992 AUTH_ASYNC,
14993 ERR_INVALID_AUTH_CREDENTIALS,
14994 4,
14995 kNoSSL,
14996 {TestRound(kGetProxy, kProxyChallenge, OK),
14997 TestRound(kGetProxy, kProxyChallenge, OK),
14998 TestRound(kGetProxyAuth, kServerChallenge, OK),
14999 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215000 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115001 {__LINE__,
15002 nullptr,
asankac93076192016-10-03 15:46:0215003 AUTH_NONE,
15004 OK,
15005 kSecureServer,
15006 AUTH_NONE,
15007 OK,
15008 1,
15009 0,
15010 {TestRound(kGet, kSuccess, OK)}},
15011 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115012 {__LINE__,
15013 nullptr,
asankac93076192016-10-03 15:46:0215014 AUTH_NONE,
15015 OK,
15016 kSecureServer,
15017 AUTH_SYNC,
15018 OK,
15019 2,
15020 0,
15021 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515022 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115023 {__LINE__,
15024 nullptr,
asankac93076192016-10-03 15:46:0215025 AUTH_NONE,
15026 OK,
15027 kSecureServer,
15028 AUTH_SYNC,
15029 ERR_INVALID_AUTH_CREDENTIALS,
15030 2,
15031 0,
asankae2257db2016-10-11 22:03:1615032 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115033 {__LINE__,
15034 nullptr,
asankac93076192016-10-03 15:46:0215035 AUTH_NONE,
15036 OK,
15037 kSecureServer,
15038 AUTH_ASYNC,
15039 OK,
15040 2,
15041 0,
15042 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515043 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115044 {__LINE__,
15045 nullptr,
asankac93076192016-10-03 15:46:0215046 AUTH_NONE,
15047 OK,
15048 kSecureServer,
15049 AUTH_ASYNC,
15050 ERR_INVALID_AUTH_CREDENTIALS,
15051 2,
15052 0,
asankae2257db2016-10-11 22:03:1615053 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215054 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115055 {__LINE__,
15056 kProxy,
asankac93076192016-10-03 15:46:0215057 AUTH_NONE,
15058 OK,
15059 kSecureServer,
15060 AUTH_NONE,
15061 OK,
15062 1,
15063 0,
15064 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
15065 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115066 {__LINE__,
15067 kProxy,
asankac93076192016-10-03 15:46:0215068 AUTH_NONE,
15069 OK,
15070 kSecureServer,
15071 AUTH_SYNC,
15072 OK,
15073 2,
15074 0,
15075 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515076 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115077 {__LINE__,
15078 kProxy,
asankac93076192016-10-03 15:46:0215079 AUTH_NONE,
15080 OK,
15081 kSecureServer,
15082 AUTH_SYNC,
15083 ERR_INVALID_AUTH_CREDENTIALS,
15084 2,
15085 0,
15086 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615087 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115088 {__LINE__,
15089 kProxy,
asankac93076192016-10-03 15:46:0215090 AUTH_NONE,
15091 OK,
15092 kSecureServer,
15093 AUTH_ASYNC,
15094 OK,
15095 2,
15096 0,
15097 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515098 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115099 {__LINE__,
15100 kProxy,
asankac93076192016-10-03 15:46:0215101 AUTH_NONE,
15102 OK,
15103 kSecureServer,
15104 AUTH_ASYNC,
15105 ERR_INVALID_AUTH_CREDENTIALS,
15106 2,
15107 0,
15108 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615109 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215110 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115111 {__LINE__,
15112 kProxy,
asankac93076192016-10-03 15:46:0215113 AUTH_SYNC,
15114 OK,
15115 kSecureServer,
15116 AUTH_NONE,
15117 OK,
15118 2,
15119 1,
15120 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515121 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115122 {__LINE__,
15123 kProxy,
asankac93076192016-10-03 15:46:0215124 AUTH_SYNC,
15125 ERR_INVALID_AUTH_CREDENTIALS,
15126 kSecureServer,
15127 AUTH_NONE,
15128 OK,
15129 2,
15130 kNoSSL,
15131 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615132 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115133 {__LINE__,
15134 kProxy,
asankae2257db2016-10-11 22:03:1615135 AUTH_SYNC,
15136 ERR_UNSUPPORTED_AUTH_SCHEME,
15137 kSecureServer,
15138 AUTH_NONE,
15139 OK,
15140 2,
15141 kNoSSL,
15142 {TestRound(kConnect, kProxyChallenge, OK),
15143 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115144 {__LINE__,
15145 kProxy,
asankae2257db2016-10-11 22:03:1615146 AUTH_SYNC,
15147 ERR_UNEXPECTED,
15148 kSecureServer,
15149 AUTH_NONE,
15150 OK,
15151 2,
15152 kNoSSL,
15153 {TestRound(kConnect, kProxyChallenge, OK),
15154 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115155 {__LINE__,
15156 kProxy,
asankac93076192016-10-03 15:46:0215157 AUTH_ASYNC,
15158 OK,
15159 kSecureServer,
15160 AUTH_NONE,
15161 OK,
15162 2,
15163 1,
15164 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515165 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115166 {__LINE__,
15167 kProxy,
asankac93076192016-10-03 15:46:0215168 AUTH_ASYNC,
15169 ERR_INVALID_AUTH_CREDENTIALS,
15170 kSecureServer,
15171 AUTH_NONE,
15172 OK,
15173 2,
15174 kNoSSL,
15175 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615176 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215177 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115178 {__LINE__,
15179 kProxy,
asankac93076192016-10-03 15:46:0215180 AUTH_SYNC,
15181 OK,
15182 kSecureServer,
15183 AUTH_SYNC,
15184 OK,
15185 3,
15186 1,
15187 {TestRound(kConnect, kProxyChallenge, OK),
15188 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15189 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515190 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115191 {__LINE__,
15192 kProxy,
asankac93076192016-10-03 15:46:0215193 AUTH_SYNC,
15194 OK,
15195 kSecureServer,
15196 AUTH_SYNC,
15197 ERR_INVALID_AUTH_CREDENTIALS,
15198 3,
15199 1,
15200 {TestRound(kConnect, kProxyChallenge, OK),
15201 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15202 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615203 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115204 {__LINE__,
15205 kProxy,
asankac93076192016-10-03 15:46:0215206 AUTH_ASYNC,
15207 OK,
15208 kSecureServer,
15209 AUTH_SYNC,
15210 OK,
15211 3,
15212 1,
15213 {TestRound(kConnect, kProxyChallenge, OK),
15214 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15215 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515216 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115217 {__LINE__,
15218 kProxy,
asankac93076192016-10-03 15:46:0215219 AUTH_ASYNC,
15220 OK,
15221 kSecureServer,
15222 AUTH_SYNC,
15223 ERR_INVALID_AUTH_CREDENTIALS,
15224 3,
15225 1,
15226 {TestRound(kConnect, kProxyChallenge, OK),
15227 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15228 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615229 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115230 {__LINE__,
15231 kProxy,
asankac93076192016-10-03 15:46:0215232 AUTH_SYNC,
15233 OK,
15234 kSecureServer,
15235 AUTH_ASYNC,
15236 OK,
15237 3,
15238 1,
15239 {TestRound(kConnect, kProxyChallenge, OK),
15240 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15241 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515242 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115243 {__LINE__,
15244 kProxy,
asankac93076192016-10-03 15:46:0215245 AUTH_SYNC,
15246 OK,
15247 kSecureServer,
15248 AUTH_ASYNC,
15249 ERR_INVALID_AUTH_CREDENTIALS,
15250 3,
15251 1,
15252 {TestRound(kConnect, kProxyChallenge, OK),
15253 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15254 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615255 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115256 {__LINE__,
15257 kProxy,
asankac93076192016-10-03 15:46:0215258 AUTH_ASYNC,
15259 OK,
15260 kSecureServer,
15261 AUTH_ASYNC,
15262 OK,
15263 3,
15264 1,
15265 {TestRound(kConnect, kProxyChallenge, OK),
15266 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15267 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515268 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115269 {__LINE__,
15270 kProxy,
asankac93076192016-10-03 15:46:0215271 AUTH_ASYNC,
15272 OK,
15273 kSecureServer,
15274 AUTH_ASYNC,
15275 ERR_INVALID_AUTH_CREDENTIALS,
15276 3,
15277 1,
15278 {TestRound(kConnect, kProxyChallenge, OK),
15279 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15280 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615281 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115282 {__LINE__,
15283 kProxy,
15284 AUTH_ASYNC,
15285 ERR_INVALID_AUTH_CREDENTIALS,
15286 kSecureServer,
15287 AUTH_ASYNC,
15288 ERR_INVALID_AUTH_CREDENTIALS,
15289 4,
15290 2,
15291 {TestRound(kConnect, kProxyChallenge, OK),
15292 TestRound(kConnect, kProxyChallenge, OK),
15293 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15294 &kServerChallenge),
15295 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515296 };
15297
asanka463ca4262016-11-16 02:34:3115298 for (const auto& test_config : test_configs) {
15299 SCOPED_TRACE(::testing::Message() << "Test config at "
15300 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815301 HttpAuthHandlerMock::Factory* auth_factory(
15302 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715303 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915304 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615305
15306 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515307 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115308 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815309 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15310 std::string auth_challenge = "Mock realm=proxy";
15311 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415312 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15313 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815314 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2015315 empty_ssl_info, origin,
15316 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815317 auth_handler->SetGenerateExpectation(
15318 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115319 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815320 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15321 }
[email protected]044de0642010-06-17 10:42:1515322 }
15323 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015324 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515325 std::string auth_challenge = "Mock realm=server";
15326 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415327 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15328 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515329 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015330 empty_ssl_info, origin,
15331 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515332 auth_handler->SetGenerateExpectation(
15333 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115334 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815335 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615336
15337 // The second handler always succeeds. It should only be used where there
15338 // are multiple auth sessions for server auth in the same network
15339 // transaction using the same auth scheme.
15340 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915341 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615342 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
15343 empty_ssl_info, origin,
15344 NetLogWithSource());
15345 second_handler->SetGenerateExpectation(true, OK);
15346 auth_factory->AddMockHandler(second_handler.release(),
15347 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515348 }
15349 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915350 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615351 ConfiguredProxyResolutionService::CreateFixed(
15352 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515353 } else {
Bence Béky53a5aef2018-03-29 21:54:1215354 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615355 ConfiguredProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515356 }
15357
15358 HttpRequestInfo request;
15359 request.method = "GET";
15360 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1015361 request.traffic_annotation =
15362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515363
danakj1fd259a02016-04-16 03:17:0915364 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515365
rchcb68dc62015-05-21 04:45:3615366 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15367
15368 std::vector<std::vector<MockRead>> mock_reads(1);
15369 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515370 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215371 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515372 const TestRound& read_write_round = test_config.rounds[round];
15373
15374 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615375 mock_reads.back().push_back(read_write_round.read);
15376 mock_writes.back().push_back(read_write_round.write);
15377
15378 // kProxyChallenge uses Proxy-Connection: close which means that the
15379 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415380 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615381 mock_reads.push_back(std::vector<MockRead>());
15382 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515383 }
15384
rchcb68dc62015-05-21 04:45:3615385 if (read_write_round.extra_read) {
15386 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515387 }
rchcb68dc62015-05-21 04:45:3615388 if (read_write_round.extra_write) {
15389 mock_writes.back().push_back(*read_write_round.extra_write);
15390 }
[email protected]044de0642010-06-17 10:42:1515391
15392 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515393 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715394 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515395 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615396 }
[email protected]044de0642010-06-17 10:42:1515397
danakj1fd259a02016-04-16 03:17:0915398 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615399 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915400 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115401 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615402 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215403 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615404 }
15405
mmenkecc2298e2015-12-07 18:20:1815406 // Transaction must be created after DataProviders, so it's destroyed before
15407 // they are as well.
15408 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15409
rchcb68dc62015-05-21 04:45:3615410 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215411 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615412 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515413 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115414 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515415 int rv;
15416 if (round == 0) {
tfarina42834112016-09-22 13:38:2015417 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515418 } else {
[email protected]49639fa2011-12-20 23:22:4115419 rv = trans.RestartWithAuth(
15420 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515421 }
15422 if (rv == ERR_IO_PENDING)
15423 rv = callback.WaitForResult();
15424
15425 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615426 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015427 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515428 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515429 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15430 continue;
15431 }
15432 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815433 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515434 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815435 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615436 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515437 }
15438 }
[email protected]e5ae96a2010-04-14 20:12:4515439 }
15440}
15441
bncd16676a2016-07-20 16:23:0115442TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415443 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415444 HttpAuthHandlerMock::Factory* auth_factory(
15445 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715446 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215447 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615448 ConfiguredProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715449 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415450
15451 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15452 auth_handler->set_connection_based(true);
15453 std::string auth_challenge = "Mock realm=server";
15454 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415455 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15456 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915457 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415458 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015459 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815460 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415461
[email protected]c871bce92010-07-15 21:51:1415462 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515463 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415464 HttpRequestInfo request;
15465 request.method = "GET";
15466 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1015467 request.traffic_annotation =
15468 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715469
danakj1fd259a02016-04-16 03:17:0915470 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015471
15472 // Use a TCP Socket Pool with only one connection per group. This is used
15473 // to validate that the TCP socket is not released to the pool between
15474 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215475 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615476 CommonConnectJobParams common_connect_job_params(
15477 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815478 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915479 50, // Max sockets for pool
15480 1, // Max sockets per group
15481 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615482 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215483 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915484 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015485 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15486 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815487 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015488
bnc691fda62016-08-12 00:43:1615489 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115490 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415491
15492 const MockWrite kGet(
15493 "GET / HTTP/1.1\r\n"
15494 "Host: www.example.com\r\n"
15495 "Connection: keep-alive\r\n\r\n");
15496 const MockWrite kGetAuth(
15497 "GET / HTTP/1.1\r\n"
15498 "Host: www.example.com\r\n"
15499 "Connection: keep-alive\r\n"
15500 "Authorization: auth_token\r\n\r\n");
15501
15502 const MockRead kServerChallenge(
15503 "HTTP/1.1 401 Unauthorized\r\n"
15504 "WWW-Authenticate: Mock realm=server\r\n"
15505 "Content-Type: text/html; charset=iso-8859-1\r\n"
15506 "Content-Length: 14\r\n\r\n"
15507 "Unauthorized\r\n");
15508 const MockRead kSuccess(
15509 "HTTP/1.1 200 OK\r\n"
15510 "Content-Type: text/html; charset=iso-8859-1\r\n"
15511 "Content-Length: 3\r\n\r\n"
15512 "Yes");
15513
15514 MockWrite writes[] = {
15515 // First round
15516 kGet,
15517 // Second round
15518 kGetAuth,
15519 // Third round
15520 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015521 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015522 kGetAuth,
15523 // Competing request
15524 kGet,
[email protected]c871bce92010-07-15 21:51:1415525 };
15526 MockRead reads[] = {
15527 // First round
15528 kServerChallenge,
15529 // Second round
15530 kServerChallenge,
15531 // Third round
[email protected]eca50e122010-09-11 14:03:3015532 kServerChallenge,
15533 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415534 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015535 // Competing response
15536 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415537 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115538 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715539 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415540
Matt Menkef6edce752019-03-19 17:21:5615541 const ClientSocketPool::GroupId kSocketGroup(
15542 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415543 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15544 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015545
15546 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415547 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015548 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415549 if (rv == ERR_IO_PENDING)
15550 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115551 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615552 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215553 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815554 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315555 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115556 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15557 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415558
[email protected]7ef4cbbb2011-02-06 11:19:1015559 // In between rounds, another request comes in for the same domain.
15560 // It should not be able to grab the TCP socket that trans has already
15561 // claimed.
bnc691fda62016-08-12 00:43:1615562 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115563 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015564 rv = trans_compete.Start(&request, callback_compete.callback(),
15565 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115566 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015567 // callback_compete.WaitForResult at this point would stall forever,
15568 // since the HttpNetworkTransaction does not release the request back to
15569 // the pool until after authentication completes.
15570
15571 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415572 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615573 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415574 if (rv == ERR_IO_PENDING)
15575 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115576 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615577 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215578 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815579 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315580 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115581 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15582 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415583
[email protected]7ef4cbbb2011-02-06 11:19:1015584 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415585 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615586 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415587 if (rv == ERR_IO_PENDING)
15588 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115589 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615590 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215591 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815592 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315593 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115594 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15595 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015596
[email protected]7ef4cbbb2011-02-06 11:19:1015597 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015598 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615599 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015600 if (rv == ERR_IO_PENDING)
15601 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115602 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615603 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215604 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815605 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315606 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015607
asanka463ca4262016-11-16 02:34:3115608 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15609 // auth handler should transition to a DONE state in concert with the remote
15610 // server. But that's not something we can test here with a mock handler.
15611 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15612 auth_handler->state());
15613
[email protected]7ef4cbbb2011-02-06 11:19:1015614 // Read the body since the fourth round was successful. This will also
15615 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415616 scoped_refptr<IOBufferWithSize> io_buf =
15617 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615618 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015619 if (rv == ERR_IO_PENDING)
15620 rv = callback.WaitForResult();
15621 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615622 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015623 EXPECT_EQ(0, rv);
15624 // There are still 0 idle sockets, since the trans_compete transaction
15625 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315626 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015627
15628 // The competing request can now finish. Wait for the headers and then
15629 // read the body.
15630 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115631 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615632 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015633 if (rv == ERR_IO_PENDING)
15634 rv = callback.WaitForResult();
15635 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615636 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015637 EXPECT_EQ(0, rv);
15638
15639 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315640 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415641}
15642
[email protected]65041fa2010-05-21 06:56:5315643// This tests the case that a request is issued via http instead of spdy after
15644// npn is negotiated.
bncd16676a2016-07-20 16:23:0115645TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315646 HttpRequestInfo request;
15647 request.method = "GET";
bncce36dca22015-04-21 22:11:2315648 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015649 request.traffic_annotation =
15650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315651
15652 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315653 MockWrite(
15654 "GET / HTTP/1.1\r\n"
15655 "Host: www.example.org\r\n"
15656 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315657 };
15658
15659 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215660 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315661 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215662 MockRead("\r\n"),
15663 MockRead("hello world"),
15664 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315665 };
15666
[email protected]8ddf8322012-02-23 18:08:0615667 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615668 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315669
[email protected]bb88e1d32013-05-03 23:11:0715670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315671
Ryan Sleevib8d7ea02018-05-07 20:01:0115672 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715673 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315674
[email protected]49639fa2011-12-20 23:22:4115675 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315676
danakj1fd259a02016-04-16 03:17:0915677 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615678 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315679
tfarina42834112016-09-22 13:38:2015680 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315681
robpercival214763f2016-07-01 23:27:0115682 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15683 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315684
bnc691fda62016-08-12 00:43:1615685 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215686 ASSERT_TRUE(response);
15687 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315688 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15689
15690 std::string response_data;
bnc691fda62016-08-12 00:43:1615691 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315692 EXPECT_EQ("hello world", response_data);
15693
15694 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215695 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315696}
[email protected]26ef6582010-06-24 02:30:4715697
bnc55ff9da2015-08-19 18:42:3515698// Simulate the SSL handshake completing with an NPN negotiation followed by an
15699// immediate server closing of the socket.
15700// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115701TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715702 HttpRequestInfo request;
15703 request.method = "GET";
bncce36dca22015-04-21 22:11:2315704 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015705 request.traffic_annotation =
15706 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715707
[email protected]8ddf8322012-02-23 18:08:0615708 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615709 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715710 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715711
Ryan Hamilton0239aac2018-05-19 00:03:1315712 spdy::SpdySerializedFrame req(
15713 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115714 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715715
15716 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615717 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715718 };
15719
Ryan Sleevib8d7ea02018-05-07 20:01:0115720 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715721 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715722
[email protected]49639fa2011-12-20 23:22:4115723 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715724
danakj1fd259a02016-04-16 03:17:0915725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615726 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715727
tfarina42834112016-09-22 13:38:2015728 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115729 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15730 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715731}
[email protected]65d34382010-07-01 18:12:2615732
[email protected]795cbf82013-07-22 09:37:2715733// A subclass of HttpAuthHandlerMock that records the request URL when
15734// it gets it. This is needed since the auth handler may get destroyed
15735// before we get a chance to query it.
15736class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
15737 public:
15738 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
15739
Chris Watkins7a41d3552017-12-01 02:13:2715740 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2715741
15742 protected:
dchengb03027d2014-10-21 12:00:2015743 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
15744 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0915745 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2015746 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2715747 *url_ = request->url;
15748 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0915749 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2715750 }
15751
15752 private:
15753 GURL* url_;
15754};
15755
[email protected]8e6441ca2010-08-19 05:56:3815756// Test that if we cancel the transaction as the connection is completing, that
15757// everything tears down correctly.
bncd16676a2016-07-20 16:23:0115758TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3815759 // Setup everything about the connection to complete synchronously, so that
15760 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
15761 // for is the callback from the HttpStreamRequest.
15762 // Then cancel the transaction.
15763 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3615764 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3815765 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615766 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
15767 MockRead(SYNCHRONOUS, "hello world"),
15768 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3815769 };
15770
[email protected]8e6441ca2010-08-19 05:56:3815771 HttpRequestInfo request;
15772 request.method = "GET";
bncce36dca22015-04-21 22:11:2315773 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015774 request.traffic_annotation =
15775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3815776
danakj1fd259a02016-04-16 03:17:0915777 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5815778 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1915779 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2715780
Ryan Sleevib8d7ea02018-05-07 20:01:0115781 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3815782 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0715783 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3815784
[email protected]49639fa2011-12-20 23:22:4115785 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3815786
Matt Muellerd9342e3a2019-11-26 01:41:1415787 RecordingBoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4115788 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115789 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3815790 trans.reset(); // Cancel the transaction here.
15791
fdoray92e35a72016-06-10 15:54:5515792 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3015793}
15794
[email protected]ecab6e052014-05-16 14:58:1215795// Test that if a transaction is cancelled after receiving the headers, the
15796// stream is drained properly and added back to the socket pool. The main
15797// purpose of this test is to make sure that an HttpStreamParser can be read
15798// from after the HttpNetworkTransaction and the objects it owns have been
15799// deleted.
15800// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0115801TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1215802 MockRead data_reads[] = {
15803 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
15804 MockRead(ASYNC, "Content-Length: 2\r\n"),
15805 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
15806 MockRead(ASYNC, "1"),
15807 // 2 async reads are necessary to trigger a ReadResponseBody call after the
15808 // HttpNetworkTransaction has been deleted.
15809 MockRead(ASYNC, "2"),
15810 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
15811 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115812 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1215813 session_deps_.socket_factory->AddSocketDataProvider(&data);
15814
danakj1fd259a02016-04-16 03:17:0915815 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1215816
15817 {
15818 HttpRequestInfo request;
15819 request.method = "GET";
bncce36dca22015-04-21 22:11:2315820 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015821 request.traffic_annotation =
15822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1215823
dcheng48459ac22014-08-26 00:46:4115824 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1215825 TestCompletionCallback callback;
15826
tfarina42834112016-09-22 13:38:2015827 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115828 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1215829 callback.WaitForResult();
15830
15831 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215832 ASSERT_TRUE(response);
15833 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1215834 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15835
15836 // The transaction and HttpRequestInfo are deleted.
15837 }
15838
15839 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515840 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215841
15842 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115843 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215844}
15845
[email protected]76a505b2010-08-25 06:23:0015846// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115847TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915848 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615849 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4915850 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1415851 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715852 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015854
[email protected]76a505b2010-08-25 06:23:0015855 HttpRequestInfo request;
15856 request.method = "GET";
bncce36dca22015-04-21 22:11:2315857 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015858 request.traffic_annotation =
15859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015860
15861 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315862 MockWrite(
15863 "GET http://www.example.org/ HTTP/1.1\r\n"
15864 "Host: www.example.org\r\n"
15865 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015866 };
15867
15868 MockRead data_reads1[] = {
15869 MockRead("HTTP/1.1 200 OK\r\n"),
15870 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15871 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615872 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015873 };
15874
Ryan Sleevib8d7ea02018-05-07 20:01:0115875 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715876 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015877
[email protected]49639fa2011-12-20 23:22:4115878 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015879
bnc691fda62016-08-12 00:43:1615880 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915881 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615882 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915883 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15884 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015885
bnc691fda62016-08-12 00:43:1615886 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015888
15889 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115890 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015891
bnc691fda62016-08-12 00:43:1615892 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215893 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015894
15895 EXPECT_TRUE(response->headers->IsKeepAlive());
15896 EXPECT_EQ(200, response->headers->response_code());
15897 EXPECT_EQ(100, response->headers->GetContentLength());
15898 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715899 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15900 HostPortPair::FromString("myproxy:70")),
15901 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915902 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15903 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15904 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015905 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015906
15907 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615908 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015909 TestLoadTimingNotReusedWithPac(load_timing_info,
15910 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015911}
15912
15913// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115914TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915915 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615916 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4915917 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1415918 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715919 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915920 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015921
[email protected]76a505b2010-08-25 06:23:0015922 HttpRequestInfo request;
15923 request.method = "GET";
bncce36dca22015-04-21 22:11:2315924 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015925 request.traffic_annotation =
15926 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015927
15928 // Since we have proxy, should try to establish tunnel.
15929 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715930 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15931 "Host: www.example.org:443\r\n"
15932 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015933
rsleevidb16bb02015-11-12 23:47:1715934 MockWrite("GET / HTTP/1.1\r\n"
15935 "Host: www.example.org\r\n"
15936 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015937 };
15938
15939 MockRead data_reads1[] = {
15940 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15941
15942 MockRead("HTTP/1.1 200 OK\r\n"),
15943 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15944 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615945 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015946 };
15947
Ryan Sleevib8d7ea02018-05-07 20:01:0115948 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715949 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615950 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715951 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015952
[email protected]49639fa2011-12-20 23:22:4115953 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015954
bnc691fda62016-08-12 00:43:1615955 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915956 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615957 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915958 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15959 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015960
bnc691fda62016-08-12 00:43:1615961 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015963
15964 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115965 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415966 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015967 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015968 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15969 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015970 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015971 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015972 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15973 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015974
bnc691fda62016-08-12 00:43:1615975 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215976 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015977
15978 EXPECT_TRUE(response->headers->IsKeepAlive());
15979 EXPECT_EQ(200, response->headers->response_code());
15980 EXPECT_EQ(100, response->headers->GetContentLength());
15981 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15982 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715983 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15984 HostPortPair::FromString("myproxy:70")),
15985 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915986 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15987 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15988 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015989
15990 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615991 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015992 TestLoadTimingNotReusedWithPac(load_timing_info,
15993 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015994}
15995
rsleevidb16bb02015-11-12 23:47:1715996// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15997// literal host.
bncd16676a2016-07-20 16:23:0115998TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915999 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616000 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916001 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416002 RecordingBoundTestNetLog log;
rsleevidb16bb02015-11-12 23:47:1716003 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916004 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1716005
16006 HttpRequestInfo request;
16007 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1516008 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1016009 request.traffic_annotation =
16010 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1716011
16012 // Since we have proxy, should try to establish tunnel.
16013 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1516014 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
16015 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1716016 "Proxy-Connection: keep-alive\r\n\r\n"),
16017
16018 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1516019 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1716020 "Connection: keep-alive\r\n\r\n"),
16021 };
16022
16023 MockRead data_reads1[] = {
16024 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16025
16026 MockRead("HTTP/1.1 200 OK\r\n"),
16027 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16028 MockRead("Content-Length: 100\r\n\r\n"),
16029 MockRead(SYNCHRONOUS, OK),
16030 };
16031
Ryan Sleevib8d7ea02018-05-07 20:01:0116032 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1716033 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16034 SSLSocketDataProvider ssl(ASYNC, OK);
16035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16036
16037 TestCompletionCallback callback1;
16038
bnc691fda62016-08-12 00:43:1616039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1716040
bnc691fda62016-08-12 00:43:1616041 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1716043
16044 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116045 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416046 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1716047 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016048 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16049 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716050 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016051 entries, pos,
16052 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16053 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716054
bnc691fda62016-08-12 00:43:1616055 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216056 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1716057
16058 EXPECT_TRUE(response->headers->IsKeepAlive());
16059 EXPECT_EQ(200, response->headers->response_code());
16060 EXPECT_EQ(100, response->headers->GetContentLength());
16061 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16062 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716063 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16064 HostPortPair::FromString("myproxy:70")),
16065 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1716066
16067 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616068 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1716069 TestLoadTimingNotReusedWithPac(load_timing_info,
16070 CONNECT_TIMING_HAS_SSL_TIMES);
16071}
16072
[email protected]76a505b2010-08-25 06:23:0016073// Test a basic HTTPS GET request through a proxy, but the server hangs up
16074// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0116075TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616076 session_deps_.proxy_resolution_service =
16077 ConfiguredProxyResolutionService::CreateFixed(
16078 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416079 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716080 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916081 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016082
[email protected]76a505b2010-08-25 06:23:0016083 HttpRequestInfo request;
16084 request.method = "GET";
bncce36dca22015-04-21 22:11:2316085 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016086 request.traffic_annotation =
16087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016088
16089 // Since we have proxy, should try to establish tunnel.
16090 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716091 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16092 "Host: www.example.org:443\r\n"
16093 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016094
rsleevidb16bb02015-11-12 23:47:1716095 MockWrite("GET / HTTP/1.1\r\n"
16096 "Host: www.example.org\r\n"
16097 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016098 };
16099
16100 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0016101 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616102 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0016103 };
16104
Ryan Sleevib8d7ea02018-05-07 20:01:0116105 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716106 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616107 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016109
[email protected]49639fa2011-12-20 23:22:4116110 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016111
bnc691fda62016-08-12 00:43:1616112 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5016113
bnc691fda62016-08-12 00:43:1616114 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116115 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016116
16117 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116118 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5416119 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016120 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016121 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16122 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016123 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016124 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016125 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16126 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016127}
16128
[email protected]749eefa82010-09-13 22:14:0316129// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0116130TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1316131 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4916132 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116133 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0316134
Raul Tambre94493c652019-03-11 17:18:3516135 spdy::SpdySerializedFrame resp(
16136 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316137 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0316138 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116139 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0316140 };
16141
Ryan Sleevib8d7ea02018-05-07 20:01:0116142 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716143 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0316144
[email protected]8ddf8322012-02-23 18:08:0616145 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616146 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0316148
danakj1fd259a02016-04-16 03:17:0916149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0316150
16151 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2316152 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4016153 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1116154 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3416155 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16156 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716157 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216158 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316159
16160 HttpRequestInfo request;
16161 request.method = "GET";
bncce36dca22015-04-21 22:11:2316162 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016163 request.traffic_annotation =
16164 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316165
bnc691fda62016-08-12 00:43:1616166 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316167
[email protected]41d64e82013-07-03 22:44:2616168 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016169 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116170 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16171 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316172}
16173
[email protected]73b8dd222010-11-11 19:55:2416174// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616175// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216176void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716177 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916178 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716179 request_info.url = GURL("https://www.example.com/");
16180 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916181 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016182 request_info.traffic_annotation =
16183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716184
[email protected]8ddf8322012-02-23 18:08:0616185 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916186 MockWrite data_writes[] = {
16187 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416188 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116189 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716190 session_deps_.socket_factory->AddSocketDataProvider(&data);
16191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416192
danakj1fd259a02016-04-16 03:17:0916193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616194 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416195
[email protected]49639fa2011-12-20 23:22:4116196 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016197 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916198 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416199 rv = callback.WaitForResult();
16200 ASSERT_EQ(error, rv);
16201}
16202
bncd16676a2016-07-20 16:23:0116203TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416204 // Just check a grab bag of cert errors.
16205 static const int kErrors[] = {
16206 ERR_CERT_COMMON_NAME_INVALID,
16207 ERR_CERT_AUTHORITY_INVALID,
16208 ERR_CERT_DATE_INVALID,
16209 };
Avi Drissman4365a4782018-12-28 19:26:2416210 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616211 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16212 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416213 }
16214}
16215
[email protected]bd0b6772011-01-11 19:59:3016216// Ensure that a client certificate is removed from the SSL client auth
16217// cache when:
16218// 1) No proxy is involved.
16219// 2) TLS False Start is disabled.
16220// 3) The initial TLS handshake requests a client certificate.
16221// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116222TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916223 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716224 request_info.url = GURL("https://www.example.com/");
16225 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916226 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016227 request_info.traffic_annotation =
16228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716229
David Benjamin1c4b6d012019-07-08 17:12:5716230 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116231 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016232
16233 // [ssl_]data1 contains the data for the first SSL handshake. When a
16234 // CertificateRequest is received for the first time, the handshake will
16235 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916236 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016237 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116239 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716240 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016241
16242 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16243 // False Start is not being used, the result of the SSL handshake will be
16244 // returned as part of the SSLClientSocket::Connect() call. This test
16245 // matches the result of a server sending a handshake_failure alert,
16246 // rather than a Finished message, because it requires a client
16247 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916248 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016249 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716250 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116251 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716252 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016253
16254 // [ssl_]data3 contains the data for the third SSL handshake. When a
16255 // connection to a server fails during an SSL handshake,
David Benjamin07a07d652020-02-26 22:26:5916256 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
16257 // enabled on some errors. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016258 // of the HttpNetworkTransaction. Because this test failure is due to
16259 // requiring a client certificate, this fallback handshake should also
16260 // fail.
ttuttle859dc7a2015-04-23 19:42:2916261 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
David Benjamin07a07d652020-02-26 22:26:5916262 ssl_data3.expected_disable_legacy_crypto = false;
[email protected]bd0b6772011-01-11 19:59:3016263 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116265 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716266 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016267
danakj1fd259a02016-04-16 03:17:0916268 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616269 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016270
[email protected]bd0b6772011-01-11 19:59:3016271 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116272 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016273 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116274 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016275
16276 // Complete the SSL handshake, which should abort due to requiring a
16277 // client certificate.
16278 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116279 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016280
16281 // Indicate that no certificate should be supplied. From the perspective
16282 // of SSLClientCertCache, NULL is just as meaningful as a real
16283 // certificate, so this is the same as supply a
16284 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516285 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116286 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016287
16288 // Ensure the certificate was added to the client auth cache before
16289 // allowing the connection to continue restarting.
16290 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416291 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116292 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416293 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216294 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016295
16296 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716297 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16298 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016299 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116300 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016301
16302 // Ensure that the client certificate is removed from the cache on a
16303 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116304 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416305 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016306}
16307
16308// Ensure that a client certificate is removed from the SSL client auth
16309// cache when:
16310// 1) No proxy is involved.
16311// 2) TLS False Start is enabled.
16312// 3) The initial TLS handshake requests a client certificate.
16313// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116314TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916315 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716316 request_info.url = GURL("https://www.example.com/");
16317 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916318 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016319 request_info.traffic_annotation =
16320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716321
David Benjamin1c4b6d012019-07-08 17:12:5716322 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116323 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016324
16325 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16326 // return successfully after reading up to the peer's Certificate message.
16327 // This is to allow the caller to call SSLClientSocket::Write(), which can
16328 // enqueue application data to be sent in the same packet as the
16329 // ChangeCipherSpec and Finished messages.
16330 // The actual handshake will be finished when SSLClientSocket::Read() is
16331 // called, which expects to process the peer's ChangeCipherSpec and
16332 // Finished messages. If there was an error negotiating with the peer,
16333 // such as due to the peer requiring a client certificate when none was
16334 // supplied, the alert sent by the peer won't be processed until Read() is
16335 // called.
16336
16337 // Like the non-False Start case, when a client certificate is requested by
16338 // the peer, the handshake is aborted during the Connect() call.
16339 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916340 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016341 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716342 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116343 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716344 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016345
16346 // When a client certificate is supplied, Connect() will not be aborted
16347 // when the peer requests the certificate. Instead, the handshake will
16348 // artificially succeed, allowing the caller to write the HTTP request to
16349 // the socket. The handshake messages are not processed until Read() is
16350 // called, which then detects that the handshake was aborted, due to the
16351 // peer sending a handshake_failure because it requires a client
16352 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916353 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016354 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716355 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916356 MockRead data2_reads[] = {
16357 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016358 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116359 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716360 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016361
16362 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716363 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16364 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916365 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016366 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716367 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116368 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716369 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016370
[email protected]80c75f682012-05-26 16:22:1716371 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16372 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916373 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716374 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716375 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116376 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716377 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716378
[email protected]7799de12013-05-30 05:52:5116379 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916380 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116381 ssl_data5.cert_request_info = cert_request.get();
16382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116383 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116384 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16385
danakj1fd259a02016-04-16 03:17:0916386 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616387 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016388
[email protected]bd0b6772011-01-11 19:59:3016389 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116390 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016391 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116392 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016393
16394 // Complete the SSL handshake, which should abort due to requiring a
16395 // client certificate.
16396 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116397 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016398
16399 // Indicate that no certificate should be supplied. From the perspective
16400 // of SSLClientCertCache, NULL is just as meaningful as a real
16401 // certificate, so this is the same as supply a
16402 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516403 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116404 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016405
16406 // Ensure the certificate was added to the client auth cache before
16407 // allowing the connection to continue restarting.
16408 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416409 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116410 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416411 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216412 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016413
[email protected]bd0b6772011-01-11 19:59:3016414 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716415 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16416 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016417 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116418 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016419
16420 // Ensure that the client certificate is removed from the cache on a
16421 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116422 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416423 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016424}
16425
[email protected]8c405132011-01-11 22:03:1816426// Ensure that a client certificate is removed from the SSL client auth
16427// cache when:
16428// 1) An HTTPS proxy is involved.
16429// 3) The HTTPS proxy requests a client certificate.
16430// 4) The client supplies an invalid/unacceptable certificate for the
16431// proxy.
bncd16676a2016-07-20 16:23:0116432TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616433 session_deps_.proxy_resolution_service =
16434 ConfiguredProxyResolutionService::CreateFixed(
16435 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416436 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716437 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816438
David Benjamin3b94b0f2019-04-25 23:07:5216439 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116440 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816441
David Benjamin3b94b0f2019-04-25 23:07:5216442 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16443 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916444 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816445 requests[0].url = GURL("https://www.example.com/");
16446 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916447 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016448 requests[0].traffic_annotation =
16449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816450
David Benjamin3b94b0f2019-04-25 23:07:5216451 // HTTPS requests are tunneled.
16452 MockWrite https_writes[] = {
16453 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16454 "Host: www.example.com:443\r\n"
16455 "Proxy-Connection: keep-alive\r\n\r\n"),
16456 };
16457
[email protected]8c405132011-01-11 22:03:1816458 requests[1].url = GURL("http://www.example.com/");
16459 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916460 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016461 requests[1].traffic_annotation =
16462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816463
David Benjamin3b94b0f2019-04-25 23:07:5216464 // HTTP requests are not.
16465 MockWrite http_writes[] = {
16466 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16467 "Host: www.example.com\r\n"
16468 "Proxy-Connection: keep-alive\r\n\r\n"),
16469 };
[email protected]8c405132011-01-11 22:03:1816470
David Benjamin3b94b0f2019-04-25 23:07:5216471 // When the server rejects the client certificate, it will close the
16472 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16473 // TLS 1.2 with False Start), the error is returned out of the first Read().
16474 for (bool reject_in_connect : {true, false}) {
16475 SCOPED_TRACE(reject_in_connect);
16476 // Client certificate errors are typically signaled with
16477 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16478 // protocol error.
16479 for (Error reject_error :
16480 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16481 SCOPED_TRACE(reject_error);
16482 // Tunneled and non-tunneled requests are handled differently. Test both.
16483 for (const HttpRequestInfo& request : requests) {
16484 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816485
David Benjamin3b94b0f2019-04-25 23:07:5216486 session_deps_.socket_factory =
16487 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816488
David Benjamin3b94b0f2019-04-25 23:07:5216489 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
David Benjamin07a07d652020-02-26 22:26:5916490 // [ssl_]data[1-3].
David Benjamin3b94b0f2019-04-25 23:07:5216491 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16492 ssl_data1.cert_request_info = cert_request.get();
16493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16494 StaticSocketDataProvider data1;
16495 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816496
David Benjamin3b94b0f2019-04-25 23:07:5216497 base::Optional<SSLSocketDataProvider> ssl_data2;
16498 base::Optional<StaticSocketDataProvider> data2;
16499 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16500 if (reject_in_connect) {
16501 ssl_data2.emplace(ASYNC, reject_error);
16502 // There are no reads or writes.
16503 data2.emplace();
16504 } else {
16505 ssl_data2.emplace(ASYNC, OK);
16506 // We will get one Write() in before observing the error in Read().
16507 if (request.url.SchemeIsCryptographic()) {
16508 data2.emplace(error_in_read, https_writes);
16509 } else {
16510 data2.emplace(error_in_read, http_writes);
16511 }
16512 }
16513 ssl_data2->cert_request_info = cert_request.get();
David Benjamin3b94b0f2019-04-25 23:07:5216514 session_deps_.socket_factory->AddSSLSocketDataProvider(
16515 &ssl_data2.value());
16516 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816517
David Benjamin07a07d652020-02-26 22:26:5916518 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
16519 // connect twice.
16520 base::Optional<SSLSocketDataProvider> ssl_data3;
16521 base::Optional<StaticSocketDataProvider> data3;
16522 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
16523 ssl_data3.emplace(ASYNC, reject_error);
16524 data3.emplace(); // There are no reads or writes.
16525 ssl_data3->cert_request_info = cert_request.get();
16526 session_deps_.socket_factory->AddSSLSocketDataProvider(
16527 &ssl_data3.value());
16528 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
16529 }
16530
David Benjamin3b94b0f2019-04-25 23:07:5216531 std::unique_ptr<HttpNetworkSession> session =
16532 CreateSession(&session_deps_);
16533 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16534
16535 // Begin the SSL handshake with the proxy.
16536 TestCompletionCallback callback;
16537 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16538 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16539
16540 // Complete the SSL handshake, which should abort due to requiring a
16541 // client certificate.
16542 rv = callback.WaitForResult();
16543 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16544
16545 // Indicate that no certificate should be supplied. From the
16546 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16547 // real certificate, so this is the same as supply a
16548 // legitimate-but-unacceptable certificate.
16549 rv =
16550 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16551 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16552
16553 // Ensure the certificate was added to the client auth cache before
16554 // allowing the connection to continue restarting.
16555 scoped_refptr<X509Certificate> client_cert;
16556 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116557 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216558 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16559 ASSERT_FALSE(client_cert);
16560 // Ensure the certificate was NOT cached for the endpoint. This only
16561 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116562 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216563 HostPortPair("www.example.com", 443), &client_cert,
16564 &client_private_key));
16565
16566 // Restart the handshake. This will consume ssl_data2. The result code
16567 // is checked against what ssl_data2 should return.
16568 rv = callback.WaitForResult();
16569 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16570 IsError(reject_error)));
16571
16572 // Now that the new handshake has failed, ensure that the client
16573 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116574 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216575 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116576 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216577 HostPortPair("www.example.com", 443), &client_cert,
16578 &client_private_key));
16579 }
16580 }
[email protected]8c405132011-01-11 22:03:1816581 }
16582}
16583
David Benjamin1a0566082019-04-30 07:36:1916584// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16585// requests during a TLS renegotiation.
16586TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16587 HttpRequestInfo request_info;
16588 request_info.url = GURL("https://www.example.com/");
16589 request_info.method = "GET";
16590 request_info.load_flags = LOAD_NORMAL;
16591 request_info.traffic_annotation =
16592 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16593
16594 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16595 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16596
16597 std::unique_ptr<FakeClientCertIdentity> identity =
16598 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16599 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16600 ASSERT_TRUE(identity);
16601
16602 // The first connection's handshake succeeds, but we get
16603 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16604 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16605 ssl_data1.cert_request_info = cert_request.get();
16606 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16607 MockWrite data1_writes[] = {
16608 MockWrite("GET / HTTP/1.1\r\n"
16609 "Host: www.example.com\r\n"
16610 "Connection: keep-alive\r\n\r\n"),
16611 };
16612 MockRead data1_reads[] = {
16613 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16614 };
16615 StaticSocketDataProvider data1(data1_reads, data1_writes);
16616 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16617
16618 // After supplying with certificate, we restart the request from the top,
16619 // which succeeds this time.
16620 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16621 ssl_data2.expected_send_client_cert = true;
16622 ssl_data2.expected_client_cert = identity->certificate();
16623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16624 MockWrite data2_writes[] = {
16625 MockWrite("GET / HTTP/1.1\r\n"
16626 "Host: www.example.com\r\n"
16627 "Connection: keep-alive\r\n\r\n"),
16628 };
16629 MockRead data2_reads[] = {
16630 MockRead("HTTP/1.1 200 OK\r\n"
16631 "Content-Length: 0\r\n\r\n"),
16632 };
16633 StaticSocketDataProvider data2(data2_reads, data2_writes);
16634 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16635
16636 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16637 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16638
16639 TestCompletionCallback callback;
16640 int rv = callback.GetResult(
16641 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16642 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16643
16644 rv = trans.RestartWithCertificate(identity->certificate(),
16645 identity->ssl_private_key(),
16646 callback.callback());
16647 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16648
16649 // Ensure the certificate was added to the client auth cache
16650 // allowing the connection to continue restarting.
16651 scoped_refptr<X509Certificate> client_cert;
16652 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116653 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916654 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16655 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16656
16657 // Complete the handshake. The request now succeeds.
16658 rv = callback.WaitForResult();
16659 ASSERT_THAT(rv, IsError(OK));
16660 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16661
16662 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116663 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916664 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16665 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16666}
16667
bncd16676a2016-07-20 16:23:0116668TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616669 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916670 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916671 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616672
bnc032658ba2016-09-26 18:17:1516673 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616674
Ryan Hamilton0239aac2018-05-19 00:03:1316675 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916676 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816677 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316678 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716679 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616680 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116681 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616682 };
Ryan Hamilton0239aac2018-05-19 00:03:1316683 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516684 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316685 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116686 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316687 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516688 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316689 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116690 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616691 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116692 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16693 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316694 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616695 };
16696
eroman36d84e54432016-03-17 03:23:0216697 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216698 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116699 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716700 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616701
[email protected]aa22b242011-11-16 18:58:2916702 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616703 HttpRequestInfo request1;
16704 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316705 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616706 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016707 request1.traffic_annotation =
16708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016709 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616710
tfarina42834112016-09-22 13:38:2016711 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116712 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16713 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616714
16715 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216716 ASSERT_TRUE(response);
16717 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216718 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616719
16720 std::string response_data;
robpercival214763f2016-07-01 23:27:0116721 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616722 EXPECT_EQ("hello!", response_data);
16723
bnca4d611d2016-09-22 19:55:3716724 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316725 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316726 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16727 base::nullopt);
robpercival214763f2016-07-01 23:27:0116728 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616729
16730 HttpRequestInfo request2;
16731 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716732 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616733 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016734 request2.traffic_annotation =
16735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016736 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616737
tfarina42834112016-09-22 13:38:2016738 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116739 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16740 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616741
16742 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216743 ASSERT_TRUE(response);
16744 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216745 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616746 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216747 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116748 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616749 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616750}
16751
bncd16676a2016-07-20 16:23:0116752TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0216753 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916754 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916755 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0216756
bnc032658ba2016-09-26 18:17:1516757 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0216758
Ryan Hamilton0239aac2018-05-19 00:03:1316759 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916760 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816761 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316762 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716763 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0216764 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116765 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0216766 };
Ryan Hamilton0239aac2018-05-19 00:03:1316767 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516768 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316769 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116770 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316771 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516772 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316773 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116774 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0216775 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116776 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16777 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316778 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0216779 };
16780
eroman36d84e54432016-03-17 03:23:0216781 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216782 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116783 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716784 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0216785
16786 TestCompletionCallback callback;
16787 HttpRequestInfo request1;
16788 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316789 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0216790 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016791 request1.traffic_annotation =
16792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016793 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216794
tfarina42834112016-09-22 13:38:2016795 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116796 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16797 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216798
16799 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216800 ASSERT_TRUE(response);
16801 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216802 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216803
16804 std::string response_data;
robpercival214763f2016-07-01 23:27:0116805 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216806 EXPECT_EQ("hello!", response_data);
16807
16808 HttpRequestInfo request2;
16809 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716810 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0216811 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016812 request2.traffic_annotation =
16813 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016814 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216815
tfarina42834112016-09-22 13:38:2016816 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116817 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16818 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216819
16820 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216821 ASSERT_TRUE(response);
16822 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216823 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216824 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216825 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116826 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216827 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0216828}
16829
bnc8016c1f2017-03-31 02:11:2916830// Regression test for https://crbug.com/546991.
16831// The server might not be able to serve an IP pooled request, and might send a
16832// 421 Misdirected Request response status to indicate this.
16833// HttpNetworkTransaction should reset the request and retry without IP pooling.
16834TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
16835 // Two hosts resolve to the same IP address.
16836 const std::string ip_addr = "1.2.3.4";
16837 IPAddress ip;
16838 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16839 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16840
Jeremy Roman0579ed62017-08-29 15:56:1916841 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916842 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16843 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16844
16845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16846
16847 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316848 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916849 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16850 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316851 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916852 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316853 spdy::SpdySerializedFrame rst(
16854 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916855 MockWrite writes1[] = {
16856 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16857 CreateMockWrite(rst, 6),
16858 };
16859
16860 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316861 spdy::SpdySerializedFrame resp1(
16862 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16863 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16864 spdy::SpdyHeaderBlock response_headers;
16865 response_headers[spdy::kHttp2StatusHeader] = "421";
16866 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916867 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16868 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16869 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16870
16871 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116872 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916873 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16874
16875 AddSSLSocketData();
16876
16877 // Retry the second request on a second connection.
16878 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316879 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916880 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16881 MockWrite writes2[] = {
16882 CreateMockWrite(req3, 0),
16883 };
16884
Ryan Hamilton0239aac2018-05-19 00:03:1316885 spdy::SpdySerializedFrame resp3(
16886 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16887 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916888 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16889 MockRead(ASYNC, 0, 3)};
16890
16891 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116892 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916893 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16894
16895 AddSSLSocketData();
16896
16897 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316898 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316899 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16900 base::nullopt);
bnc8016c1f2017-03-31 02:11:2916901 EXPECT_THAT(rv, IsOk());
16902
16903 HttpRequestInfo request1;
16904 request1.method = "GET";
16905 request1.url = GURL("https://www.example.org/");
16906 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016907 request1.traffic_annotation =
16908 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916909 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16910
Eric Orthf4db66a2019-02-19 21:35:3316911 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916912 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16914 rv = callback.WaitForResult();
16915 EXPECT_THAT(rv, IsOk());
16916
16917 const HttpResponseInfo* response = trans1.GetResponseInfo();
16918 ASSERT_TRUE(response);
16919 ASSERT_TRUE(response->headers);
16920 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16921 EXPECT_TRUE(response->was_fetched_via_spdy);
16922 EXPECT_TRUE(response->was_alpn_negotiated);
16923 std::string response_data;
16924 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16925 EXPECT_EQ("hello!", response_data);
16926
16927 HttpRequestInfo request2;
16928 request2.method = "GET";
16929 request2.url = GURL("https://mail.example.org/");
16930 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016931 request2.traffic_annotation =
16932 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916933 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16934
Matt Muellerd9342e3a2019-11-26 01:41:1416935 RecordingBoundTestNetLog log;
bnc8016c1f2017-03-31 02:11:2916936 rv = trans2.Start(&request2, callback.callback(), log.bound());
16937 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16938 rv = callback.WaitForResult();
16939 EXPECT_THAT(rv, IsOk());
16940
16941 response = trans2.GetResponseInfo();
16942 ASSERT_TRUE(response);
16943 ASSERT_TRUE(response->headers);
16944 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16945 EXPECT_TRUE(response->was_fetched_via_spdy);
16946 EXPECT_TRUE(response->was_alpn_negotiated);
16947 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16948 EXPECT_EQ("hello!", response_data);
16949
Eric Roman79cc7552019-07-19 02:17:5416950 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916951 ExpectLogContainsSomewhere(
16952 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916953 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916954}
16955
16956// Test that HTTP 421 responses are properly returned to the caller if received
16957// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16958// portions of the response.
16959TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16960 // Two hosts resolve to the same IP address.
16961 const std::string ip_addr = "1.2.3.4";
16962 IPAddress ip;
16963 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16964 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16965
Jeremy Roman0579ed62017-08-29 15:56:1916966 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916967 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16968 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16969
16970 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16971
16972 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316973 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916974 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16975 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316976 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916977 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316978 spdy::SpdySerializedFrame rst(
16979 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916980 MockWrite writes1[] = {
16981 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16982 CreateMockWrite(rst, 6),
16983 };
16984
16985 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316986 spdy::SpdySerializedFrame resp1(
16987 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16988 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16989 spdy::SpdyHeaderBlock response_headers;
16990 response_headers[spdy::kHttp2StatusHeader] = "421";
16991 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916992 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16993 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16994 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16995
16996 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116997 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916998 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16999
17000 AddSSLSocketData();
17001
17002 // Retry the second request on a second connection. It returns 421 Misdirected
17003 // Retry again.
17004 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317005 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5917006 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17007 MockWrite writes2[] = {
17008 CreateMockWrite(req3, 0),
17009 };
17010
Ryan Hamilton0239aac2018-05-19 00:03:1317011 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5917012 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1317013 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5917014 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17015 MockRead(ASYNC, 0, 3)};
17016
17017 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117018 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5917019 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17020
17021 AddSSLSocketData();
17022
17023 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317024 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317025 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17026 base::nullopt);
davidbence688ae2017-05-04 15:12:5917027 EXPECT_THAT(rv, IsOk());
17028
17029 HttpRequestInfo request1;
17030 request1.method = "GET";
17031 request1.url = GURL("https://www.example.org/");
17032 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017033 request1.traffic_annotation =
17034 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917035 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17036
Eric Orthf4db66a2019-02-19 21:35:3317037 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5917038 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17039 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17040 rv = callback.WaitForResult();
17041 EXPECT_THAT(rv, IsOk());
17042
17043 const HttpResponseInfo* response = trans1.GetResponseInfo();
17044 ASSERT_TRUE(response);
17045 ASSERT_TRUE(response->headers);
17046 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17047 EXPECT_TRUE(response->was_fetched_via_spdy);
17048 EXPECT_TRUE(response->was_alpn_negotiated);
17049 std::string response_data;
17050 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17051 EXPECT_EQ("hello!", response_data);
17052
17053 HttpRequestInfo request2;
17054 request2.method = "GET";
17055 request2.url = GURL("https://mail.example.org/");
17056 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017057 request2.traffic_annotation =
17058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917059 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17060
Matt Muellerd9342e3a2019-11-26 01:41:1417061 RecordingBoundTestNetLog log;
davidbence688ae2017-05-04 15:12:5917062 rv = trans2.Start(&request2, callback.callback(), log.bound());
17063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17064 rv = callback.WaitForResult();
17065 EXPECT_THAT(rv, IsOk());
17066
17067 // After a retry, the 421 Misdirected Request is reported back up to the
17068 // caller.
17069 response = trans2.GetResponseInfo();
17070 ASSERT_TRUE(response);
17071 ASSERT_TRUE(response->headers);
17072 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
17073 EXPECT_TRUE(response->was_fetched_via_spdy);
17074 EXPECT_TRUE(response->was_alpn_negotiated);
17075 EXPECT_TRUE(response->ssl_info.cert);
17076 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17077 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2917078}
17079
bncd16676a2016-07-20 16:23:0117080TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1317081 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3417082 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
17083 session_deps_.host_resolver =
17084 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0917085 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617086
bnc032658ba2016-09-26 18:17:1517087 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617088
Ryan Hamilton0239aac2018-05-19 00:03:1317089 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917090 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817091 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317092 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717093 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617094 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117095 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617096 };
Ryan Hamilton0239aac2018-05-19 00:03:1317097 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517098 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317099 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117100 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317101 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517102 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317103 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117104 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617105 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117106 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17107 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317108 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617109 };
17110
eroman36d84e54432016-03-17 03:23:0217111 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217112 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117113 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717114 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617115
[email protected]aa22b242011-11-16 18:58:2917116 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617117 HttpRequestInfo request1;
17118 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317119 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617120 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017121 request1.traffic_annotation =
17122 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017123 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617124
tfarina42834112016-09-22 13:38:2017125 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117126 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17127 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617128
17129 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217130 ASSERT_TRUE(response);
17131 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217132 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617133
17134 std::string response_data;
robpercival214763f2016-07-01 23:27:0117135 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617136 EXPECT_EQ("hello!", response_data);
17137
17138 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317139 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317140 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17141 base::nullopt);
robpercival214763f2016-07-01 23:27:0117142 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617143
17144 HttpRequestInfo request2;
17145 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717146 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617147 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017148 request2.traffic_annotation =
17149 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017150 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617151
tfarina42834112016-09-22 13:38:2017152 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117153 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17154 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617155
17156 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217157 ASSERT_TRUE(response);
17158 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217159 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617160 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217161 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117162 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617163 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617164}
17165
bncd16676a2016-07-20 16:23:0117166TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317167 const std::string https_url = "https://www.example.org:8080/";
17168 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417169
17170 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317171 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917172 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417173
17174 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117175 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417176 };
17177
Raul Tambre94493c652019-03-11 17:18:3517178 spdy::SpdySerializedFrame resp1(
17179 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317180 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117181 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917182 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417183
Ryan Sleevib8d7ea02018-05-07 20:01:0117184 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417185 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717186 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417187
17188 // HTTP GET for the HTTP URL
17189 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317190 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417191 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317192 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417193 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417194 };
17195
17196 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317197 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17198 MockRead(ASYNC, 2, "hello"),
17199 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417200 };
17201
Ryan Sleevib8d7ea02018-05-07 20:01:0117202 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417203
[email protected]8450d722012-07-02 19:14:0417204 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617205 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717206 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17207 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17208 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417209
danakj1fd259a02016-04-16 03:17:0917210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417211
17212 // Start the first transaction to set up the SpdySession
17213 HttpRequestInfo request1;
17214 request1.method = "GET";
17215 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417216 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017217 request1.traffic_annotation =
17218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017219 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417220 TestCompletionCallback callback1;
17221 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017222 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517223 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417224
robpercival214763f2016-07-01 23:27:0117225 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417226 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17227
17228 // Now, start the HTTP request
17229 HttpRequestInfo request2;
17230 request2.method = "GET";
17231 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417232 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017233 request2.traffic_annotation =
17234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017235 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417236 TestCompletionCallback callback2;
17237 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017238 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517239 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417240
robpercival214763f2016-07-01 23:27:0117241 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417242 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17243}
17244
bnc5452e2a2015-05-08 16:27:4217245// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17246// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117247TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517248 url::SchemeHostPort server("https", "www.example.org", 443);
17249 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217250
bnc8bef8da22016-05-30 01:28:2517251 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217252 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617253 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217254 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17255
17256 // No data should be read from the alternative, because HTTP/1.1 is
17257 // negotiated.
17258 StaticSocketDataProvider data;
17259 session_deps_.socket_factory->AddSocketDataProvider(&data);
17260
17261 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617262 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217263 // mocked. This way the request relies on the alternate Job.
17264 StaticSocketDataProvider data_refused;
17265 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17266 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17267
zhongyi3d4a55e72016-04-22 20:36:4617268 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917269 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017270 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217271 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117272 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217273 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117274 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717275 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217276
bnc5452e2a2015-05-08 16:27:4217277 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617278 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217279 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517280 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1017281 request.traffic_annotation =
17282 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217283 TestCompletionCallback callback;
17284
17285 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217286 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017287 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217288 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217289}
17290
bnc40448a532015-05-11 19:13:1417291// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617292// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417293// succeeds, the request should succeed, even if the latter fails because
17294// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117295TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517296 url::SchemeHostPort server("https", "www.example.org", 443);
17297 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417298
17299 // Negotiate HTTP/1.1 with alternative.
17300 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617301 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417302 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17303
17304 // No data should be read from the alternative, because HTTP/1.1 is
17305 // negotiated.
17306 StaticSocketDataProvider data;
17307 session_deps_.socket_factory->AddSocketDataProvider(&data);
17308
zhongyi3d4a55e72016-04-22 20:36:4617309 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417310 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617311 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417312 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17313
17314 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517315 MockWrite("GET / HTTP/1.1\r\n"
17316 "Host: www.example.org\r\n"
17317 "Connection: keep-alive\r\n\r\n"),
17318 MockWrite("GET /second HTTP/1.1\r\n"
17319 "Host: www.example.org\r\n"
17320 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417321 };
17322
17323 MockRead http_reads[] = {
17324 MockRead("HTTP/1.1 200 OK\r\n"),
17325 MockRead("Content-Type: text/html\r\n"),
17326 MockRead("Content-Length: 6\r\n\r\n"),
17327 MockRead("foobar"),
17328 MockRead("HTTP/1.1 200 OK\r\n"),
17329 MockRead("Content-Type: text/html\r\n"),
17330 MockRead("Content-Length: 7\r\n\r\n"),
17331 MockRead("another"),
17332 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117333 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417334 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17335
zhongyi3d4a55e72016-04-22 20:36:4617336 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917337 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017338 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417339 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117340 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217341 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117342 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717343 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417344
17345 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17346 HttpRequestInfo request1;
17347 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517348 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417349 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017350 request1.traffic_annotation =
17351 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417352 TestCompletionCallback callback1;
17353
tfarina42834112016-09-22 13:38:2017354 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417355 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117356 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417357
17358 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217359 ASSERT_TRUE(response1);
17360 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417361 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17362
17363 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117364 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417365 EXPECT_EQ("foobar", response_data1);
17366
17367 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17368 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517369 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17370 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417371
zhongyi3d4a55e72016-04-22 20:36:4617372 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417373 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617374 // to server.
bnc40448a532015-05-11 19:13:1417375 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17376 HttpRequestInfo request2;
17377 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517378 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417379 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017380 request2.traffic_annotation =
17381 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417382 TestCompletionCallback callback2;
17383
tfarina42834112016-09-22 13:38:2017384 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417385 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117386 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417387
17388 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217389 ASSERT_TRUE(response2);
17390 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417391 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17392
17393 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117394 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417395 EXPECT_EQ("another", response_data2);
17396}
17397
bnc5452e2a2015-05-08 16:27:4217398// Alternative service requires HTTP/2 (or SPDY), but there is already a
17399// HTTP/1.1 socket open to the alternative server. That socket should not be
17400// used.
bncd16676a2016-07-20 16:23:0117401TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617402 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217403 HostPortPair alternative("alternative.example.org", 443);
17404 std::string origin_url = "https://origin.example.org:443";
17405 std::string alternative_url = "https://alternative.example.org:443";
17406
17407 // Negotiate HTTP/1.1 with alternative.example.org.
17408 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617409 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217410 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17411
17412 // HTTP/1.1 data for |request1| and |request2|.
17413 MockWrite http_writes[] = {
17414 MockWrite(
17415 "GET / HTTP/1.1\r\n"
17416 "Host: alternative.example.org\r\n"
17417 "Connection: keep-alive\r\n\r\n"),
17418 MockWrite(
17419 "GET / HTTP/1.1\r\n"
17420 "Host: alternative.example.org\r\n"
17421 "Connection: keep-alive\r\n\r\n"),
17422 };
17423
17424 MockRead http_reads[] = {
17425 MockRead(
17426 "HTTP/1.1 200 OK\r\n"
17427 "Content-Type: text/html; charset=iso-8859-1\r\n"
17428 "Content-Length: 40\r\n\r\n"
17429 "first HTTP/1.1 response from alternative"),
17430 MockRead(
17431 "HTTP/1.1 200 OK\r\n"
17432 "Content-Type: text/html; charset=iso-8859-1\r\n"
17433 "Content-Length: 41\r\n\r\n"
17434 "second HTTP/1.1 response from alternative"),
17435 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117436 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217437 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17438
17439 // This test documents that an alternate Job should not pool to an already
17440 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617441 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217442 StaticSocketDataProvider data_refused;
17443 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17444 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17445
zhongyi3d4a55e72016-04-22 20:36:4617446 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917447 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017448 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217449 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117450 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217451 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117452 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717453 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217454
17455 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217456 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617457 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217458 request1.method = "GET";
17459 request1.url = GURL(alternative_url);
17460 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017461 request1.traffic_annotation =
17462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217463 TestCompletionCallback callback1;
17464
tfarina42834112016-09-22 13:38:2017465 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117466 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617467 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217468 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217469 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217470 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217471 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217472 EXPECT_FALSE(response1->was_fetched_via_spdy);
17473 std::string response_data1;
bnc691fda62016-08-12 00:43:1617474 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217475 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17476
17477 // Request for origin.example.org, which has an alternative service. This
17478 // will start two Jobs: the alternative looks for connections to pool to,
17479 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617480 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217481 // this request fails.
bnc5452e2a2015-05-08 16:27:4217482 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617483 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217484 request2.method = "GET";
17485 request2.url = GURL(origin_url);
17486 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017487 request2.traffic_annotation =
17488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217489 TestCompletionCallback callback2;
17490
tfarina42834112016-09-22 13:38:2017491 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117492 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217493
17494 // Another transaction to alternative. This is to test that the HTTP/1.1
17495 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217496 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617497 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217498 request3.method = "GET";
17499 request3.url = GURL(alternative_url);
17500 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017501 request3.traffic_annotation =
17502 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217503 TestCompletionCallback callback3;
17504
tfarina42834112016-09-22 13:38:2017505 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117506 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617507 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217508 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217509 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217510 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217511 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217512 EXPECT_FALSE(response3->was_fetched_via_spdy);
17513 std::string response_data3;
bnc691fda62016-08-12 00:43:1617514 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217515 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17516}
17517
bncd16676a2016-07-20 16:23:0117518TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317519 const std::string https_url = "https://www.example.org:8080/";
17520 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417521
rdsmithebb50aa2015-11-12 03:44:3817522 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117523 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817524
[email protected]8450d722012-07-02 19:14:0417525 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317526 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417527 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17528 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17529 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317530 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917531 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317532 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217533 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917534
17535 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1317536 spdy::SpdyHeaderBlock req2_block;
17537 req2_block[spdy::kHttp2MethodHeader] = "GET";
17538 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17539 req2_block[spdy::kHttp2SchemeHeader] = "http";
17540 req2_block[spdy::kHttp2PathHeader] = "/";
17541 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517542 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417543
17544 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117545 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17546 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417547 };
17548
Ryan Hamilton0239aac2018-05-19 00:03:1317549 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517550 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317551 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517552 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317553 spdy::SpdySerializedFrame body1(
17554 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17555 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817556 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317557 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817558 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517559 spdy::SpdySerializedFrame resp2(
17560 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317561 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317562 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117563 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317564 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117565 CreateMockRead(wrapped_resp1, 4),
17566 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317567 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117568 CreateMockRead(resp2, 8),
17569 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317570 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17571 };
[email protected]8450d722012-07-02 19:14:0417572
Ryan Sleevib8d7ea02018-05-07 20:01:0117573 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417574 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717575 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417576
Lily Houghton8c2f97d2018-01-22 05:06:5917577 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617578 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4917579 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1417580 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717581 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417582 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617583 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417585 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617586 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317587 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17588 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417589
danakj1fd259a02016-04-16 03:17:0917590 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417591
17592 // Start the first transaction to set up the SpdySession
17593 HttpRequestInfo request1;
17594 request1.method = "GET";
17595 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417596 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017597 request1.traffic_annotation =
17598 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017599 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417600 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017601 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417602
mmenke666a6fea2015-12-19 04:16:3317603 // This pause is a hack to avoid running into https://crbug.com/497228.
17604 data1.RunUntilPaused();
17605 base::RunLoop().RunUntilIdle();
17606 data1.Resume();
robpercival214763f2016-07-01 23:27:0117607 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417608 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17609
[email protected]f6c63db52013-02-02 00:35:2217610 LoadTimingInfo load_timing_info1;
17611 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17612 TestLoadTimingNotReusedWithPac(load_timing_info1,
17613 CONNECT_TIMING_HAS_SSL_TIMES);
17614
mmenke666a6fea2015-12-19 04:16:3317615 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417616 HttpRequestInfo request2;
17617 request2.method = "GET";
17618 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417619 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017620 request2.traffic_annotation =
17621 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017622 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417623 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017624 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417625
mmenke666a6fea2015-12-19 04:16:3317626 // This pause is a hack to avoid running into https://crbug.com/497228.
17627 data1.RunUntilPaused();
17628 base::RunLoop().RunUntilIdle();
17629 data1.Resume();
robpercival214763f2016-07-01 23:27:0117630 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317631
[email protected]8450d722012-07-02 19:14:0417632 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217633
17634 LoadTimingInfo load_timing_info2;
17635 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17636 // The established SPDY sessions is considered reused by the HTTP request.
17637 TestLoadTimingReusedWithPac(load_timing_info2);
17638 // HTTP requests over a SPDY session should have a different connection
17639 // socket_log_id than requests over a tunnel.
17640 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417641}
17642
[email protected]2d88e7d2012-07-19 17:55:1717643// Test that in the case where we have a SPDY session to a SPDY proxy
17644// that we do not pool other origins that resolve to the same IP when
17645// the certificate does not match the new origin.
17646// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117647TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317648 const std::string url1 = "http://www.example.org/";
17649 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717650 const std::string ip_addr = "1.2.3.4";
17651
rdsmithebb50aa2015-11-12 03:44:3817652 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117653 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817654
[email protected]2d88e7d2012-07-19 17:55:1717655 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1317656 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2317657 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317658 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517659 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717660
17661 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117662 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717663 };
17664
Raul Tambre94493c652019-03-11 17:18:3517665 spdy::SpdySerializedFrame resp1(
17666 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317667 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717668 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117669 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17670 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717671 };
17672
Ryan Sleevib8d7ea02018-05-07 20:01:0117673 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217674 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917675 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717676 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17677 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317678 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717679
17680 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317681 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917682 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717683
17684 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117685 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717686 };
17687
Ryan Hamilton0239aac2018-05-19 00:03:1317688 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517689 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317690 spdy::SpdySerializedFrame body2(
17691 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117692 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317693 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717694
Ryan Sleevib8d7ea02018-05-07 20:01:0117695 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717696 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317697 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717698
17699 // Set up a proxy config that sends HTTP requests to a proxy, and
17700 // all others direct.
17701 ProxyConfig proxy_config;
17702 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917703 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617704 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4917705 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17706 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
17707 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1717708
bncce36dca22015-04-21 22:11:2317709 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617710 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717711 // Load a valid cert. Note, that this does not need to
17712 // be valid for proxy because the MockSSLClientSocket does
17713 // not actually verify it. But SpdySession will use this
17714 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917715 ssl1.ssl_info.cert =
17716 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17717 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17719 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717720
17721 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617722 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317723 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17724 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717725
Jeremy Roman0579ed62017-08-29 15:56:1917726 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317727 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717728 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717729
danakj1fd259a02016-04-16 03:17:0917730 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717731
17732 // Start the first transaction to set up the SpdySession
17733 HttpRequestInfo request1;
17734 request1.method = "GET";
17735 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1717736 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017737 request1.traffic_annotation =
17738 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017739 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717740 TestCompletionCallback callback1;
17741 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017742 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3317743 // This pause is a hack to avoid running into https://crbug.com/497228.
17744 data1.RunUntilPaused();
17745 base::RunLoop().RunUntilIdle();
17746 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1717747
robpercival214763f2016-07-01 23:27:0117748 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717749 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17750
17751 // Now, start the HTTP request
17752 HttpRequestInfo request2;
17753 request2.method = "GET";
17754 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1717755 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017756 request2.traffic_annotation =
17757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017758 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717759 TestCompletionCallback callback2;
17760 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017761 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517762 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1717763
17764 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0117765 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717766 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17767}
17768
[email protected]85f97342013-04-17 06:12:2417769// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
17770// error) in SPDY session, removes the socket from pool and closes the SPDY
17771// session. Verify that new url's from the same HttpNetworkSession (and a new
17772// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0117773TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2317774 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2417775
17776 MockRead reads1[] = {
17777 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
17778 };
17779
Ryan Sleevib8d7ea02018-05-07 20:01:0117780 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2417781
Ryan Hamilton0239aac2018-05-19 00:03:1317782 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917783 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2417784 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117785 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2417786 };
17787
Raul Tambre94493c652019-03-11 17:18:3517788 spdy::SpdySerializedFrame resp2(
17789 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317790 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2417791 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4117792 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
17793 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2417794 };
17795
Ryan Sleevib8d7ea02018-05-07 20:01:0117796 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2417797
[email protected]85f97342013-04-17 06:12:2417798 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617799 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17801 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2417802
17803 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617804 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017805 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2417807
danakj1fd259a02016-04-16 03:17:0917808 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5017809 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2417810
17811 // Start the first transaction to set up the SpdySession and verify that
17812 // connection was closed.
17813 HttpRequestInfo request1;
17814 request1.method = "GET";
17815 request1.url = GURL(https_url);
17816 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017817 request1.traffic_annotation =
17818 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017819 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417820 TestCompletionCallback callback1;
17821 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017822 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117823 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2417824
17825 // Now, start the second request and make sure it succeeds.
17826 HttpRequestInfo request2;
17827 request2.method = "GET";
17828 request2.url = GURL(https_url);
17829 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017830 request2.traffic_annotation =
17831 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017832 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417833 TestCompletionCallback callback2;
17834 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017835 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2417836
robpercival214763f2016-07-01 23:27:0117837 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2417838 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17839}
17840
bncd16676a2016-07-20 16:23:0117841TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317842 ClientSocketPoolManager::set_max_sockets_per_group(
17843 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17844 ClientSocketPoolManager::set_max_sockets_per_pool(
17845 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17846
17847 // Use two different hosts with different IPs so they don't get pooled.
17848 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17849 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917850 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317851
17852 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617853 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317854 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617855 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317856 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17858
Ryan Hamilton0239aac2018-05-19 00:03:1317859 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917860 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317861 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117862 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317863 };
Ryan Hamilton0239aac2018-05-19 00:03:1317864 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517865 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317866 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117867 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317868 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117869 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917870 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317871 };
17872
rdsmithebb50aa2015-11-12 03:44:3817873 // Use a separate test instance for the separate SpdySession that will be
17874 // created.
bncd16676a2016-07-20 16:23:0117875 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117876 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217877 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317878
Ryan Hamilton0239aac2018-05-19 00:03:1317879 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917880 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317881 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117882 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317883 };
Ryan Hamilton0239aac2018-05-19 00:03:1317884 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517885 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317886 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117887 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317888 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117889 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917890 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317891 };
17892
Ryan Sleevib8d7ea02018-05-07 20:01:0117893 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217894 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317895
17896 MockWrite http_write[] = {
17897 MockWrite("GET / HTTP/1.1\r\n"
17898 "Host: www.a.com\r\n"
17899 "Connection: keep-alive\r\n\r\n"),
17900 };
17901
17902 MockRead http_read[] = {
17903 MockRead("HTTP/1.1 200 OK\r\n"),
17904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17905 MockRead("Content-Length: 6\r\n\r\n"),
17906 MockRead("hello!"),
17907 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117908 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317909 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17910
17911 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117912 SpdySessionKey spdy_session_key_a(
17913 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417914 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17915 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317916 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617917 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317918
17919 TestCompletionCallback callback;
17920 HttpRequestInfo request1;
17921 request1.method = "GET";
17922 request1.url = GURL("https://www.a.com/");
17923 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017924 request1.traffic_annotation =
17925 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817926 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917927 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317928
tfarina42834112016-09-22 13:38:2017929 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117930 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17931 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317932
17933 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217934 ASSERT_TRUE(response);
17935 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217936 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317937 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217938 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317939
17940 std::string response_data;
robpercival214763f2016-07-01 23:27:0117941 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317942 EXPECT_EQ("hello!", response_data);
17943 trans.reset();
17944 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617945 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317946
17947 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117948 SpdySessionKey spdy_session_key_b(
17949 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417950 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17951 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317952 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617953 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317954 HttpRequestInfo request2;
17955 request2.method = "GET";
17956 request2.url = GURL("https://www.b.com/");
17957 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017958 request2.traffic_annotation =
17959 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817960 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917961 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317962
tfarina42834112016-09-22 13:38:2017963 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117964 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17965 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317966
17967 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217968 ASSERT_TRUE(response);
17969 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217970 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317971 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217972 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117973 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317974 EXPECT_EQ("hello!", response_data);
17975 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617976 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317977 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617978 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317979
17980 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117981 SpdySessionKey spdy_session_key_a1(
17982 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417983 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17984 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317985 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617986 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317987 HttpRequestInfo request3;
17988 request3.method = "GET";
17989 request3.url = GURL("http://www.a.com/");
17990 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017991 request3.traffic_annotation =
17992 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817993 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917994 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317995
tfarina42834112016-09-22 13:38:2017996 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117997 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17998 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317999
18000 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218001 ASSERT_TRUE(response);
18002 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0318003 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
18004 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218005 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118006 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318007 EXPECT_EQ("hello!", response_data);
18008 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618009 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318010 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618011 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318012}
18013
bncd16676a2016-07-20 16:23:0118014TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418015 HttpRequestInfo request;
18016 request.method = "GET";
bncce36dca22015-04-21 22:11:2318017 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018018 request.traffic_annotation =
18019 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418020
danakj1fd259a02016-04-16 03:17:0918021 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618022 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418023
ttuttled9dbc652015-09-29 20:00:5918024 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418025 StaticSocketDataProvider data;
18026 data.set_connect_data(mock_connect);
18027 session_deps_.socket_factory->AddSocketDataProvider(&data);
18028
18029 TestCompletionCallback callback;
18030
tfarina42834112016-09-22 13:38:2018031 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118032 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418033
18034 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118035 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418036
ttuttle1f2d7e92015-04-28 16:17:4718037 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618038 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718039 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118040 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918041
18042 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618043 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918044 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418045}
18046
bncd16676a2016-07-20 16:23:0118047TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418048 HttpRequestInfo request;
18049 request.method = "GET";
bncce36dca22015-04-21 22:11:2318050 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018051 request.traffic_annotation =
18052 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418053
danakj1fd259a02016-04-16 03:17:0918054 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618055 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418056
ttuttled9dbc652015-09-29 20:00:5918057 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418058 StaticSocketDataProvider data;
18059 data.set_connect_data(mock_connect);
18060 session_deps_.socket_factory->AddSocketDataProvider(&data);
18061
18062 TestCompletionCallback callback;
18063
tfarina42834112016-09-22 13:38:2018064 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118065 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418066
18067 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118068 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418069
ttuttle1f2d7e92015-04-28 16:17:4718070 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618071 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718072 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118073 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918074
18075 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618076 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918077 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418078}
18079
bncd16676a2016-07-20 16:23:0118080TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418081 HttpRequestInfo request;
18082 request.method = "GET";
bncce36dca22015-04-21 22:11:2318083 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018084 request.traffic_annotation =
18085 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418086
danakj1fd259a02016-04-16 03:17:0918087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618088 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418089
18090 MockWrite data_writes[] = {
18091 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18092 };
18093 MockRead data_reads[] = {
18094 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18095 };
18096
Ryan Sleevib8d7ea02018-05-07 20:01:0118097 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418098 session_deps_.socket_factory->AddSocketDataProvider(&data);
18099
18100 TestCompletionCallback callback;
18101
tfarina42834112016-09-22 13:38:2018102 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118103 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418104
18105 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118106 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418107}
18108
bncd16676a2016-07-20 16:23:0118109TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418110 HttpRequestInfo request;
18111 request.method = "GET";
bncce36dca22015-04-21 22:11:2318112 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018113 request.traffic_annotation =
18114 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418115
danakj1fd259a02016-04-16 03:17:0918116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618117 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418118
18119 MockWrite data_writes[] = {
18120 MockWrite(ASYNC, ERR_CONNECTION_RESET),
18121 };
18122 MockRead data_reads[] = {
18123 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18124 };
18125
Ryan Sleevib8d7ea02018-05-07 20:01:0118126 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418127 session_deps_.socket_factory->AddSocketDataProvider(&data);
18128
18129 TestCompletionCallback callback;
18130
tfarina42834112016-09-22 13:38:2018131 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118132 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418133
18134 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118135 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418136}
18137
bncd16676a2016-07-20 16:23:0118138TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418139 HttpRequestInfo request;
18140 request.method = "GET";
bncce36dca22015-04-21 22:11:2318141 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018142 request.traffic_annotation =
18143 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418144
danakj1fd259a02016-04-16 03:17:0918145 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618146 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418147
18148 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318149 MockWrite(
18150 "GET / HTTP/1.1\r\n"
18151 "Host: www.example.org\r\n"
18152 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418153 };
18154 MockRead data_reads[] = {
18155 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18156 };
18157
Ryan Sleevib8d7ea02018-05-07 20:01:0118158 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418159 session_deps_.socket_factory->AddSocketDataProvider(&data);
18160
18161 TestCompletionCallback callback;
18162
tfarina42834112016-09-22 13:38:2018163 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418165
18166 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118167 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418168}
18169
bncd16676a2016-07-20 16:23:0118170TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418171 HttpRequestInfo request;
18172 request.method = "GET";
bncce36dca22015-04-21 22:11:2318173 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018174 request.traffic_annotation =
18175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418176
danakj1fd259a02016-04-16 03:17:0918177 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618178 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418179
18180 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318181 MockWrite(
18182 "GET / HTTP/1.1\r\n"
18183 "Host: www.example.org\r\n"
18184 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418185 };
18186 MockRead data_reads[] = {
18187 MockRead(ASYNC, ERR_CONNECTION_RESET),
18188 };
18189
Ryan Sleevib8d7ea02018-05-07 20:01:0118190 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418191 session_deps_.socket_factory->AddSocketDataProvider(&data);
18192
18193 TestCompletionCallback callback;
18194
tfarina42834112016-09-22 13:38:2018195 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118196 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418197
18198 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118199 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418200}
18201
[email protected]043b68c82013-08-22 23:41:5218202// Tests that when a used socket is returned to the SSL socket pool, it's closed
18203// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118204TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218205 ClientSocketPoolManager::set_max_sockets_per_group(
18206 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18207 ClientSocketPoolManager::set_max_sockets_per_pool(
18208 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18209
18210 // Set up SSL request.
18211
18212 HttpRequestInfo ssl_request;
18213 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318214 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018215 ssl_request.traffic_annotation =
18216 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218217
18218 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318219 MockWrite(
18220 "GET / HTTP/1.1\r\n"
18221 "Host: www.example.org\r\n"
18222 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218223 };
18224 MockRead ssl_reads[] = {
18225 MockRead("HTTP/1.1 200 OK\r\n"),
18226 MockRead("Content-Length: 11\r\n\r\n"),
18227 MockRead("hello world"),
18228 MockRead(SYNCHRONOUS, OK),
18229 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118230 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218231 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18232
18233 SSLSocketDataProvider ssl(ASYNC, OK);
18234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18235
18236 // Set up HTTP request.
18237
18238 HttpRequestInfo http_request;
18239 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318240 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018241 http_request.traffic_annotation =
18242 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218243
18244 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318245 MockWrite(
18246 "GET / HTTP/1.1\r\n"
18247 "Host: www.example.org\r\n"
18248 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218249 };
18250 MockRead http_reads[] = {
18251 MockRead("HTTP/1.1 200 OK\r\n"),
18252 MockRead("Content-Length: 7\r\n\r\n"),
18253 MockRead("falafel"),
18254 MockRead(SYNCHRONOUS, OK),
18255 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118256 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218257 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18258
danakj1fd259a02016-04-16 03:17:0918259 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218260
18261 // Start the SSL request.
18262 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618263 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018264 ASSERT_EQ(ERR_IO_PENDING,
18265 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18266 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218267
18268 // Start the HTTP request. Pool should stall.
18269 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618270 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018271 ASSERT_EQ(ERR_IO_PENDING,
18272 http_trans.Start(&http_request, http_callback.callback(),
18273 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118274 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218275
18276 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118277 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218278 std::string response_data;
bnc691fda62016-08-12 00:43:1618279 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218280 EXPECT_EQ("hello world", response_data);
18281
18282 // The SSL socket should automatically be closed, so the HTTP request can
18283 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318284 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118285 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218286
18287 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118288 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618289 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218290 EXPECT_EQ("falafel", response_data);
18291
dcheng48459ac22014-08-26 00:46:4118292 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218293}
18294
18295// Tests that when a SSL connection is established but there's no corresponding
18296// request that needs it, the new socket is closed if the transport socket pool
18297// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118298TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218299 ClientSocketPoolManager::set_max_sockets_per_group(
18300 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18301 ClientSocketPoolManager::set_max_sockets_per_pool(
18302 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18303
18304 // Set up an ssl request.
18305
18306 HttpRequestInfo ssl_request;
18307 ssl_request.method = "GET";
18308 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1018309 ssl_request.traffic_annotation =
18310 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218311
18312 // No data will be sent on the SSL socket.
18313 StaticSocketDataProvider ssl_data;
18314 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18315
18316 SSLSocketDataProvider ssl(ASYNC, OK);
18317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18318
18319 // Set up HTTP request.
18320
18321 HttpRequestInfo http_request;
18322 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318323 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018324 http_request.traffic_annotation =
18325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218326
18327 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318328 MockWrite(
18329 "GET / HTTP/1.1\r\n"
18330 "Host: www.example.org\r\n"
18331 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218332 };
18333 MockRead http_reads[] = {
18334 MockRead("HTTP/1.1 200 OK\r\n"),
18335 MockRead("Content-Length: 7\r\n\r\n"),
18336 MockRead("falafel"),
18337 MockRead(SYNCHRONOUS, OK),
18338 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118339 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218340 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18341
danakj1fd259a02016-04-16 03:17:0918342 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218343
18344 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18345 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918346 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918347 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318348 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218349
18350 // Start the HTTP request. Pool should stall.
18351 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618352 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018353 ASSERT_EQ(ERR_IO_PENDING,
18354 http_trans.Start(&http_request, http_callback.callback(),
18355 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118356 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218357
18358 // The SSL connection will automatically be closed once the connection is
18359 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118360 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218361 std::string response_data;
bnc691fda62016-08-12 00:43:1618362 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218363 EXPECT_EQ("falafel", response_data);
18364
dcheng48459ac22014-08-26 00:46:4118365 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218366}
18367
bncd16676a2016-07-20 16:23:0118368TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918369 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218370 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918371 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218372 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418373
18374 HttpRequestInfo request;
18375 request.method = "POST";
18376 request.url = GURL("http://www.foo.com/");
18377 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018378 request.traffic_annotation =
18379 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418380
danakj1fd259a02016-04-16 03:17:0918381 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618382 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418383 // Send headers successfully, but get an error while sending the body.
18384 MockWrite data_writes[] = {
18385 MockWrite("POST / HTTP/1.1\r\n"
18386 "Host: www.foo.com\r\n"
18387 "Connection: keep-alive\r\n"
18388 "Content-Length: 3\r\n\r\n"),
18389 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18390 };
18391
18392 MockRead data_reads[] = {
18393 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18394 MockRead("hello world"),
18395 MockRead(SYNCHRONOUS, OK),
18396 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118397 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418398 session_deps_.socket_factory->AddSocketDataProvider(&data);
18399
18400 TestCompletionCallback callback;
18401
tfarina42834112016-09-22 13:38:2018402 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418404
18405 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118406 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418407
bnc691fda62016-08-12 00:43:1618408 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218409 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418410
wezca1070932016-05-26 20:30:5218411 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418412 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18413
18414 std::string response_data;
bnc691fda62016-08-12 00:43:1618415 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118416 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418417 EXPECT_EQ("hello world", response_data);
18418}
18419
18420// This test makes sure the retry logic doesn't trigger when reading an error
18421// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118422TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418423 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918424 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418425 MockWrite data_writes[] = {
18426 MockWrite("GET / HTTP/1.1\r\n"
18427 "Host: www.foo.com\r\n"
18428 "Connection: keep-alive\r\n\r\n"),
18429 MockWrite("POST / HTTP/1.1\r\n"
18430 "Host: www.foo.com\r\n"
18431 "Connection: keep-alive\r\n"
18432 "Content-Length: 3\r\n\r\n"),
18433 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18434 };
18435
18436 MockRead data_reads[] = {
18437 MockRead("HTTP/1.1 200 Peachy\r\n"
18438 "Content-Length: 14\r\n\r\n"),
18439 MockRead("first response"),
18440 MockRead("HTTP/1.1 400 Not OK\r\n"
18441 "Content-Length: 15\r\n\r\n"),
18442 MockRead("second response"),
18443 MockRead(SYNCHRONOUS, OK),
18444 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118445 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418446 session_deps_.socket_factory->AddSocketDataProvider(&data);
18447
18448 TestCompletionCallback callback;
18449 HttpRequestInfo request1;
18450 request1.method = "GET";
18451 request1.url = GURL("http://www.foo.com/");
18452 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018453 request1.traffic_annotation =
18454 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418455
bnc87dcefc2017-05-25 12:47:5818456 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918457 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018458 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118459 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418460
18461 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118462 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418463
18464 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218465 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418466
wezca1070932016-05-26 20:30:5218467 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418468 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18469
18470 std::string response_data1;
18471 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118472 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418473 EXPECT_EQ("first response", response_data1);
18474 // Delete the transaction to release the socket back into the socket pool.
18475 trans1.reset();
18476
danakj1fd259a02016-04-16 03:17:0918477 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218478 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918479 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218480 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418481
18482 HttpRequestInfo request2;
18483 request2.method = "POST";
18484 request2.url = GURL("http://www.foo.com/");
18485 request2.upload_data_stream = &upload_data_stream;
18486 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018487 request2.traffic_annotation =
18488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418489
bnc691fda62016-08-12 00:43:1618490 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018491 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418493
18494 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118495 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418496
bnc691fda62016-08-12 00:43:1618497 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218498 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418499
wezca1070932016-05-26 20:30:5218500 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418501 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18502
18503 std::string response_data2;
bnc691fda62016-08-12 00:43:1618504 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118505 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418506 EXPECT_EQ("second response", response_data2);
18507}
18508
bncd16676a2016-07-20 16:23:0118509TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418510 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918511 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218512 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918513 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218514 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418515
18516 HttpRequestInfo request;
18517 request.method = "POST";
18518 request.url = GURL("http://www.foo.com/");
18519 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018520 request.traffic_annotation =
18521 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418522
danakj1fd259a02016-04-16 03:17:0918523 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618524 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418525 // Send headers successfully, but get an error while sending the body.
18526 MockWrite data_writes[] = {
18527 MockWrite("POST / HTTP/1.1\r\n"
18528 "Host: www.foo.com\r\n"
18529 "Connection: keep-alive\r\n"
18530 "Content-Length: 3\r\n\r\n"
18531 "fo"),
18532 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18533 };
18534
18535 MockRead data_reads[] = {
18536 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18537 MockRead("hello world"),
18538 MockRead(SYNCHRONOUS, OK),
18539 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118540 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418541 session_deps_.socket_factory->AddSocketDataProvider(&data);
18542
18543 TestCompletionCallback callback;
18544
tfarina42834112016-09-22 13:38:2018545 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418547
18548 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118549 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418550
bnc691fda62016-08-12 00:43:1618551 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218552 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418553
wezca1070932016-05-26 20:30:5218554 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418555 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18556
18557 std::string response_data;
bnc691fda62016-08-12 00:43:1618558 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118559 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418560 EXPECT_EQ("hello world", response_data);
18561}
18562
18563// This tests the more common case than the previous test, where headers and
18564// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118565TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718566 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418567
18568 HttpRequestInfo request;
18569 request.method = "POST";
18570 request.url = GURL("http://www.foo.com/");
18571 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018572 request.traffic_annotation =
18573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418574
danakj1fd259a02016-04-16 03:17:0918575 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618576 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418577 // Send headers successfully, but get an error while sending the body.
18578 MockWrite data_writes[] = {
18579 MockWrite("POST / HTTP/1.1\r\n"
18580 "Host: www.foo.com\r\n"
18581 "Connection: keep-alive\r\n"
18582 "Transfer-Encoding: chunked\r\n\r\n"),
18583 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18584 };
18585
18586 MockRead data_reads[] = {
18587 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18588 MockRead("hello world"),
18589 MockRead(SYNCHRONOUS, OK),
18590 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118591 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418592 session_deps_.socket_factory->AddSocketDataProvider(&data);
18593
18594 TestCompletionCallback callback;
18595
tfarina42834112016-09-22 13:38:2018596 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118597 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418598 // Make sure the headers are sent before adding a chunk. This ensures that
18599 // they can't be merged with the body in a single send. Not currently
18600 // necessary since a chunked body is never merged with headers, but this makes
18601 // the test more future proof.
18602 base::RunLoop().RunUntilIdle();
18603
mmenkecbc2b712014-10-09 20:29:0718604 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418605
18606 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118607 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418608
bnc691fda62016-08-12 00:43:1618609 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218610 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418611
wezca1070932016-05-26 20:30:5218612 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418613 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18614
18615 std::string response_data;
bnc691fda62016-08-12 00:43:1618616 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118617 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418618 EXPECT_EQ("hello world", response_data);
18619}
18620
bncd16676a2016-07-20 16:23:0118621TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918622 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218623 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918624 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218625 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418626
18627 HttpRequestInfo request;
18628 request.method = "POST";
18629 request.url = GURL("http://www.foo.com/");
18630 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018631 request.traffic_annotation =
18632 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418633
danakj1fd259a02016-04-16 03:17:0918634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418636
18637 MockWrite data_writes[] = {
18638 MockWrite("POST / HTTP/1.1\r\n"
18639 "Host: www.foo.com\r\n"
18640 "Connection: keep-alive\r\n"
18641 "Content-Length: 3\r\n\r\n"),
18642 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18643 };
18644
18645 MockRead data_reads[] = {
18646 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18647 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18648 MockRead("hello world"),
18649 MockRead(SYNCHRONOUS, OK),
18650 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118651 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418652 session_deps_.socket_factory->AddSocketDataProvider(&data);
18653
18654 TestCompletionCallback callback;
18655
tfarina42834112016-09-22 13:38:2018656 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118657 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418658
18659 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118660 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418661
bnc691fda62016-08-12 00:43:1618662 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218663 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418664
wezca1070932016-05-26 20:30:5218665 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418666 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18667
18668 std::string response_data;
bnc691fda62016-08-12 00:43:1618669 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118670 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418671 EXPECT_EQ("hello world", response_data);
18672}
18673
bncd16676a2016-07-20 16:23:0118674TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918675 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218676 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918677 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218678 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418679
18680 HttpRequestInfo request;
18681 request.method = "POST";
18682 request.url = GURL("http://www.foo.com/");
18683 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018684 request.traffic_annotation =
18685 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418686
danakj1fd259a02016-04-16 03:17:0918687 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618688 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418689 // Send headers successfully, but get an error while sending the body.
18690 MockWrite data_writes[] = {
18691 MockWrite("POST / HTTP/1.1\r\n"
18692 "Host: www.foo.com\r\n"
18693 "Connection: keep-alive\r\n"
18694 "Content-Length: 3\r\n\r\n"),
18695 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18696 };
18697
18698 MockRead data_reads[] = {
18699 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18700 MockRead("hello world"),
18701 MockRead(SYNCHRONOUS, OK),
18702 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118703 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418704 session_deps_.socket_factory->AddSocketDataProvider(&data);
18705
18706 TestCompletionCallback callback;
18707
tfarina42834112016-09-22 13:38:2018708 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118709 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418710
18711 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118712 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418713}
18714
bncd16676a2016-07-20 16:23:0118715TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418716 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918717 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218718 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918719 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218720 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418721
18722 HttpRequestInfo request;
18723 request.method = "POST";
18724 request.url = GURL("http://www.foo.com/");
18725 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018726 request.traffic_annotation =
18727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418728
danakj1fd259a02016-04-16 03:17:0918729 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618730 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418731 // Send headers successfully, but get an error while sending the body.
18732 MockWrite data_writes[] = {
18733 MockWrite("POST / HTTP/1.1\r\n"
18734 "Host: www.foo.com\r\n"
18735 "Connection: keep-alive\r\n"
18736 "Content-Length: 3\r\n\r\n"),
18737 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18738 };
18739
18740 MockRead data_reads[] = {
18741 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18742 MockRead("HTTP/1.0 302 Redirect\r\n"),
18743 MockRead("Location: http://somewhere-else.com/\r\n"),
18744 MockRead("Content-Length: 0\r\n\r\n"),
18745 MockRead(SYNCHRONOUS, OK),
18746 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118747 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418748 session_deps_.socket_factory->AddSocketDataProvider(&data);
18749
18750 TestCompletionCallback callback;
18751
tfarina42834112016-09-22 13:38:2018752 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418754
18755 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118756 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418757}
18758
bncd16676a2016-07-20 16:23:0118759TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918760 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218761 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918762 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218763 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418764
18765 HttpRequestInfo request;
18766 request.method = "POST";
18767 request.url = GURL("http://www.foo.com/");
18768 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018769 request.traffic_annotation =
18770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418771
danakj1fd259a02016-04-16 03:17:0918772 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618773 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418774 // Send headers successfully, but get an error while sending the body.
18775 MockWrite data_writes[] = {
18776 MockWrite("POST / HTTP/1.1\r\n"
18777 "Host: www.foo.com\r\n"
18778 "Connection: keep-alive\r\n"
18779 "Content-Length: 3\r\n\r\n"),
18780 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18781 };
18782
18783 MockRead data_reads[] = {
18784 MockRead("HTTP 0.9 rocks!"),
18785 MockRead(SYNCHRONOUS, OK),
18786 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118787 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418788 session_deps_.socket_factory->AddSocketDataProvider(&data);
18789
18790 TestCompletionCallback callback;
18791
tfarina42834112016-09-22 13:38:2018792 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418794
18795 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118796 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418797}
18798
bncd16676a2016-07-20 16:23:0118799TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0918800 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218801 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918802 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218803 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418804
18805 HttpRequestInfo request;
18806 request.method = "POST";
18807 request.url = GURL("http://www.foo.com/");
18808 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018809 request.traffic_annotation =
18810 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418811
danakj1fd259a02016-04-16 03:17:0918812 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618813 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418814 // Send headers successfully, but get an error while sending the body.
18815 MockWrite data_writes[] = {
18816 MockWrite("POST / HTTP/1.1\r\n"
18817 "Host: www.foo.com\r\n"
18818 "Connection: keep-alive\r\n"
18819 "Content-Length: 3\r\n\r\n"),
18820 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18821 };
18822
18823 MockRead data_reads[] = {
18824 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
18825 MockRead(SYNCHRONOUS, OK),
18826 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118827 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418828 session_deps_.socket_factory->AddSocketDataProvider(&data);
18829
18830 TestCompletionCallback callback;
18831
tfarina42834112016-09-22 13:38:2018832 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118833 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418834
18835 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118836 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418837}
18838
Bence Békydca6bd92018-01-30 13:43:0618839#if BUILDFLAG(ENABLE_WEBSOCKETS)
18840
18841namespace {
18842
18843void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18844 headers->SetHeader("Connection", "Upgrade");
18845 headers->SetHeader("Upgrade", "websocket");
18846 headers->SetHeader("Origin", "http://www.example.org");
18847 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618848}
18849
18850} // namespace
18851
18852TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118853 for (bool secure : {true, false}) {
18854 MockWrite data_writes[] = {
18855 MockWrite("GET / HTTP/1.1\r\n"
18856 "Host: www.example.org\r\n"
18857 "Connection: Upgrade\r\n"
18858 "Upgrade: websocket\r\n"
18859 "Origin: http://www.example.org\r\n"
18860 "Sec-WebSocket-Version: 13\r\n"
18861 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18862 "Sec-WebSocket-Extensions: permessage-deflate; "
18863 "client_max_window_bits\r\n\r\n")};
18864
18865 MockRead data_reads[] = {
18866 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18867 "Upgrade: websocket\r\n"
18868 "Connection: Upgrade\r\n"
18869 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18870
Ryan Sleevib8d7ea02018-05-07 20:01:0118871 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118872 session_deps_.socket_factory->AddSocketDataProvider(&data);
18873 SSLSocketDataProvider ssl(ASYNC, OK);
18874 if (secure)
18875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618876
18877 HttpRequestInfo request;
18878 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118879 request.url =
18880 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18881 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1018882 request.traffic_annotation =
18883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618884
Bence Béky2fcf4fa2018-04-06 20:06:0118885 TestWebSocketHandshakeStreamCreateHelper
18886 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518887
Bence Béky2fcf4fa2018-04-06 20:06:0118888 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618889 HttpNetworkTransaction trans(LOW, session.get());
18890 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118891 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618892
18893 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118894 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18895 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618896
Bence Béky2fcf4fa2018-04-06 20:06:0118897 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18898 ASSERT_TRUE(stream_request);
18899 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18900 stream_request->websocket_handshake_stream_create_helper());
18901
18902 rv = callback.WaitForResult();
18903 EXPECT_THAT(rv, IsOk());
18904
18905 EXPECT_TRUE(data.AllReadDataConsumed());
18906 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618907 }
18908}
18909
Adam Rice425cf122015-01-19 06:18:2418910// Verify that proxy headers are not sent to the destination server when
18911// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118912TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418913 HttpRequestInfo request;
18914 request.method = "GET";
bncce36dca22015-04-21 22:11:2318915 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018916 request.traffic_annotation =
18917 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418918 AddWebSocketHeaders(&request.extra_headers);
18919
18920 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918921 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5618922 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4918923 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418924
danakj1fd259a02016-04-16 03:17:0918925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418926
18927 // Since a proxy is configured, try to establish a tunnel.
18928 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718929 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18930 "Host: www.example.org:443\r\n"
18931 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418932
18933 // After calling trans->RestartWithAuth(), this is the request we should
18934 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718935 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18936 "Host: www.example.org:443\r\n"
18937 "Proxy-Connection: keep-alive\r\n"
18938 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418939
rsleevidb16bb02015-11-12 23:47:1718940 MockWrite("GET / HTTP/1.1\r\n"
18941 "Host: www.example.org\r\n"
18942 "Connection: Upgrade\r\n"
18943 "Upgrade: websocket\r\n"
18944 "Origin: http://www.example.org\r\n"
18945 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518946 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18947 "Sec-WebSocket-Extensions: permessage-deflate; "
18948 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418949
18950 // The proxy responds to the connect with a 407, using a persistent
18951 // connection.
18952 MockRead data_reads[] = {
18953 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518954 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18955 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18956 "Content-Length: 0\r\n"
18957 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418958
18959 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18960
Bence Béky8d1c6052018-02-07 12:48:1518961 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18962 "Upgrade: websocket\r\n"
18963 "Connection: Upgrade\r\n"
18964 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418965
Ryan Sleevib8d7ea02018-05-07 20:01:0118966 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418967 session_deps_.socket_factory->AddSocketDataProvider(&data);
18968 SSLSocketDataProvider ssl(ASYNC, OK);
18969 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18970
Bence Béky8d1c6052018-02-07 12:48:1518971 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18972
bnc87dcefc2017-05-25 12:47:5818973 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918974 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418975 trans->SetWebSocketHandshakeStreamCreateHelper(
18976 &websocket_stream_create_helper);
18977
18978 {
18979 TestCompletionCallback callback;
18980
tfarina42834112016-09-22 13:38:2018981 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118982 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418983
18984 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118985 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418986 }
18987
18988 const HttpResponseInfo* response = trans->GetResponseInfo();
18989 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218990 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418991 EXPECT_EQ(407, response->headers->response_code());
18992
18993 {
18994 TestCompletionCallback callback;
18995
18996 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18997 callback.callback());
robpercival214763f2016-07-01 23:27:0118998 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418999
19000 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119001 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419002 }
19003
19004 response = trans->GetResponseInfo();
19005 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219006 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419007
19008 EXPECT_EQ(101, response->headers->response_code());
19009
19010 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119011 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419012}
19013
19014// Verify that proxy headers are not sent to the destination server when
19015// establishing a tunnel for an insecure WebSocket connection.
19016// This requires the authentication info to be injected into the auth cache
19017// due to crbug.com/395064
19018// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0119019TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2419020 HttpRequestInfo request;
19021 request.method = "GET";
bncce36dca22015-04-21 22:11:2319022 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019023 request.traffic_annotation =
19024 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419025 AddWebSocketHeaders(&request.extra_headers);
19026
19027 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919028 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619029 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919030 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419031
danakj1fd259a02016-04-16 03:17:0919032 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419033
19034 MockWrite data_writes[] = {
19035 // Try to establish a tunnel for the WebSocket connection, with
19036 // credentials. Because WebSockets have a separate set of socket pools,
19037 // they cannot and will not use the same TCP/IP connection as the
19038 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1519039 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
19040 "Host: www.example.org:80\r\n"
19041 "Proxy-Connection: keep-alive\r\n"
19042 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419043
Bence Béky8d1c6052018-02-07 12:48:1519044 MockWrite("GET / HTTP/1.1\r\n"
19045 "Host: www.example.org\r\n"
19046 "Connection: Upgrade\r\n"
19047 "Upgrade: websocket\r\n"
19048 "Origin: http://www.example.org\r\n"
19049 "Sec-WebSocket-Version: 13\r\n"
19050 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19051 "Sec-WebSocket-Extensions: permessage-deflate; "
19052 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419053
19054 MockRead data_reads[] = {
19055 // HTTP CONNECT with credentials.
19056 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19057
19058 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1519059 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19060 "Upgrade: websocket\r\n"
19061 "Connection: Upgrade\r\n"
19062 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419063
Ryan Sleevib8d7ea02018-05-07 20:01:0119064 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419065 session_deps_.socket_factory->AddSocketDataProvider(&data);
19066
19067 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3319068 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2619069 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
19070 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2419071
Bence Béky8d1c6052018-02-07 12:48:1519072 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19073
bnc87dcefc2017-05-25 12:47:5819074 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919075 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419076 trans->SetWebSocketHandshakeStreamCreateHelper(
19077 &websocket_stream_create_helper);
19078
19079 TestCompletionCallback callback;
19080
tfarina42834112016-09-22 13:38:2019081 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419083
19084 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119085 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419086
19087 const HttpResponseInfo* response = trans->GetResponseInfo();
19088 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219089 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419090
19091 EXPECT_EQ(101, response->headers->response_code());
19092
19093 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119094 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419095}
19096
Matt Menke1d6093e32019-03-22 17:33:4319097// WebSockets over QUIC is not supported, including over QUIC proxies.
19098TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
19099 for (bool secure : {true, false}) {
19100 SCOPED_TRACE(secure);
19101 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619102 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke1d6093e32019-03-22 17:33:4319103 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
19104 session_deps_.enable_quic = true;
19105
19106 HttpRequestInfo request;
19107 request.url =
19108 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19109 AddWebSocketHeaders(&request.extra_headers);
19110 request.traffic_annotation =
19111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19112
19113 TestWebSocketHandshakeStreamCreateHelper
19114 websocket_handshake_stream_create_helper;
19115
19116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19117 HttpNetworkTransaction trans(LOW, session.get());
19118 trans.SetWebSocketHandshakeStreamCreateHelper(
19119 &websocket_handshake_stream_create_helper);
19120
19121 TestCompletionCallback callback;
19122 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19124
19125 rv = callback.WaitForResult();
19126 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
19127 }
19128}
19129
Bence Békydca6bd92018-01-30 13:43:0619130#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
19131
bncd16676a2016-07-20 16:23:0119132TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0919133 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219134 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919135 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219136 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219137
19138 HttpRequestInfo request;
19139 request.method = "POST";
19140 request.url = GURL("http://www.foo.com/");
19141 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019142 request.traffic_annotation =
19143 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219144
danakj1fd259a02016-04-16 03:17:0919145 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619146 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219147 MockWrite data_writes[] = {
19148 MockWrite("POST / HTTP/1.1\r\n"
19149 "Host: www.foo.com\r\n"
19150 "Connection: keep-alive\r\n"
19151 "Content-Length: 3\r\n\r\n"),
19152 MockWrite("foo"),
19153 };
19154
19155 MockRead data_reads[] = {
19156 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19157 MockRead(SYNCHRONOUS, OK),
19158 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119159 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219160 session_deps_.socket_factory->AddSocketDataProvider(&data);
19161
19162 TestCompletionCallback callback;
19163
19164 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019165 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119166 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219167
19168 std::string response_data;
bnc691fda62016-08-12 00:43:1619169 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219170
Ryan Sleevib8d7ea02018-05-07 20:01:0119171 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19172 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219173}
19174
bncd16676a2016-07-20 16:23:0119175TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919176 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219177 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919178 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219179 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219180
19181 HttpRequestInfo request;
19182 request.method = "POST";
19183 request.url = GURL("http://www.foo.com/");
19184 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019185 request.traffic_annotation =
19186 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219187
danakj1fd259a02016-04-16 03:17:0919188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619189 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219190 MockWrite data_writes[] = {
19191 MockWrite("POST / HTTP/1.1\r\n"
19192 "Host: www.foo.com\r\n"
19193 "Connection: keep-alive\r\n"
19194 "Content-Length: 3\r\n\r\n"),
19195 MockWrite("foo"),
19196 };
19197
19198 MockRead data_reads[] = {
19199 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19200 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19201 MockRead(SYNCHRONOUS, OK),
19202 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119203 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219204 session_deps_.socket_factory->AddSocketDataProvider(&data);
19205
19206 TestCompletionCallback callback;
19207
19208 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019209 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119210 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219211
19212 std::string response_data;
bnc691fda62016-08-12 00:43:1619213 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219214
Ryan Sleevib8d7ea02018-05-07 20:01:0119215 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19216 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219217}
19218
bncd16676a2016-07-20 16:23:0119219TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219220 ChunkedUploadDataStream upload_data_stream(0);
19221
19222 HttpRequestInfo request;
19223 request.method = "POST";
19224 request.url = GURL("http://www.foo.com/");
19225 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019226 request.traffic_annotation =
19227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219228
danakj1fd259a02016-04-16 03:17:0919229 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619230 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219231 // Send headers successfully, but get an error while sending the body.
19232 MockWrite data_writes[] = {
19233 MockWrite("POST / HTTP/1.1\r\n"
19234 "Host: www.foo.com\r\n"
19235 "Connection: keep-alive\r\n"
19236 "Transfer-Encoding: chunked\r\n\r\n"),
19237 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19238 };
19239
19240 MockRead data_reads[] = {
19241 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19242 MockRead(SYNCHRONOUS, OK),
19243 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119244 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219245 session_deps_.socket_factory->AddSocketDataProvider(&data);
19246
19247 TestCompletionCallback callback;
19248
19249 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019250 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219251
19252 base::RunLoop().RunUntilIdle();
19253 upload_data_stream.AppendData("f", 1, false);
19254
19255 base::RunLoop().RunUntilIdle();
19256 upload_data_stream.AppendData("oo", 2, true);
19257
robpercival214763f2016-07-01 23:27:0119258 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219259
19260 std::string response_data;
bnc691fda62016-08-12 00:43:1619261 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219262
Ryan Sleevib8d7ea02018-05-07 20:01:0119263 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19264 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219265}
19266
eustasc7d27da2017-04-06 10:33:2019267void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19268 const std::string& accept_encoding,
19269 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319270 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019271 bool should_match) {
19272 HttpRequestInfo request;
19273 request.method = "GET";
19274 request.url = GURL("http://www.foo.com/");
19275 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19276 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1019277 request.traffic_annotation =
19278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019279
19280 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19281 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19282 // Send headers successfully, but get an error while sending the body.
19283 MockWrite data_writes[] = {
19284 MockWrite("GET / HTTP/1.1\r\n"
19285 "Host: www.foo.com\r\n"
19286 "Connection: keep-alive\r\n"
19287 "Accept-Encoding: "),
19288 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19289 };
19290
sky50576f32017-05-01 19:28:0319291 std::string response_code = "200 OK";
19292 std::string extra;
19293 if (!location.empty()) {
19294 response_code = "301 Redirect\r\nLocation: ";
19295 response_code.append(location);
19296 }
19297
eustasc7d27da2017-04-06 10:33:2019298 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319299 MockRead("HTTP/1.0 "),
19300 MockRead(response_code.data()),
19301 MockRead("\r\nContent-Encoding: "),
19302 MockRead(content_encoding.data()),
19303 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019304 MockRead(SYNCHRONOUS, OK),
19305 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119306 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019307 session_deps->socket_factory->AddSocketDataProvider(&data);
19308
19309 TestCompletionCallback callback;
19310
19311 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19312 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19313
19314 rv = callback.WaitForResult();
19315 if (should_match) {
19316 EXPECT_THAT(rv, IsOk());
19317 } else {
19318 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19319 }
19320}
19321
19322TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319323 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019324}
19325
19326TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319327 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19328 true);
eustasc7d27da2017-04-06 10:33:2019329}
19330
19331TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19332 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319333 "", false);
19334}
19335
19336TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19337 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19338 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019339}
19340
xunjieli96f2a402017-06-05 17:24:2719341TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19342 ProxyConfig proxy_config;
19343 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19344 proxy_config.set_pac_mandatory(true);
19345 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619346 session_deps_.proxy_resolution_service.reset(
19347 new ConfiguredProxyResolutionService(
19348 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19349 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
19350 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2719351
19352 HttpRequestInfo request;
19353 request.method = "GET";
19354 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019355 request.traffic_annotation =
19356 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719357
19358 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19359 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19360
19361 TestCompletionCallback callback;
19362
19363 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19364 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19365 EXPECT_THAT(callback.WaitForResult(),
19366 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19367}
19368
19369TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19370 ProxyConfig proxy_config;
19371 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19372 proxy_config.set_pac_mandatory(true);
19373 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19374 new MockAsyncProxyResolverFactory(false);
19375 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619376 session_deps_.proxy_resolution_service.reset(
19377 new ConfiguredProxyResolutionService(
19378 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19379 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
19380 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2719381 HttpRequestInfo request;
19382 request.method = "GET";
19383 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019384 request.traffic_annotation =
19385 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719386
19387 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19388 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19389
19390 TestCompletionCallback callback;
19391 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19392 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19393
19394 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19395 ERR_FAILED, &resolver);
19396 EXPECT_THAT(callback.WaitForResult(),
19397 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19398}
19399
19400TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919401 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619402 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919403 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719404 session_deps_.enable_quic = false;
19405 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19406
19407 HttpRequestInfo request;
19408 request.method = "GET";
19409 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019410 request.traffic_annotation =
19411 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719412
19413 TestCompletionCallback callback;
19414 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19415 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19416 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19417
19418 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19419}
19420
Douglas Creager3cb042052018-11-06 23:08:5219421//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419422// Reporting tests
19423
19424#if BUILDFLAG(ENABLE_REPORTING)
19425class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19426 protected:
19427 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619428 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419429 auto test_reporting_context = std::make_unique<TestReportingContext>(
19430 &clock_, &tick_clock_, ReportingPolicy());
19431 test_reporting_context_ = test_reporting_context.get();
19432 session_deps_.reporting_service =
19433 ReportingService::CreateForTesting(std::move(test_reporting_context));
19434 }
19435
19436 TestReportingContext* reporting_context() const {
19437 return test_reporting_context_;
19438 }
19439
19440 void clear_reporting_service() {
19441 session_deps_.reporting_service.reset();
19442 test_reporting_context_ = nullptr;
19443 }
19444
19445 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219446 void RequestPolicy(CertStatus cert_status = 0) {
19447 HttpRequestInfo request;
19448 request.method = "GET";
19449 request.url = GURL(url_);
19450 request.traffic_annotation =
19451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19452
Lily Chend3930e72019-03-01 19:31:1119453 MockWrite data_writes[] = {
19454 MockWrite("GET / HTTP/1.1\r\n"
19455 "Host: www.example.org\r\n"
19456 "Connection: keep-alive\r\n\r\n"),
19457 };
Douglas Creager134b52e2018-11-09 18:00:1419458 MockRead data_reads[] = {
19459 MockRead("HTTP/1.0 200 OK\r\n"),
19460 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19461 "\"endpoints\": [{\"url\": "
19462 "\"https://www.example.org/upload/\"}]}\r\n"),
19463 MockRead("\r\n"),
19464 MockRead("hello world"),
19465 MockRead(SYNCHRONOUS, OK),
19466 };
Douglas Creager134b52e2018-11-09 18:00:1419467
Lily Chenfec60d92019-01-24 01:16:4219468 StaticSocketDataProvider reads(data_reads, data_writes);
19469 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419470
19471 SSLSocketDataProvider ssl(ASYNC, OK);
19472 if (request.url.SchemeIsCryptographic()) {
19473 ssl.ssl_info.cert =
19474 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19475 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219476 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419477 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19478 }
19479
Douglas Creager134b52e2018-11-09 18:00:1419480 TestCompletionCallback callback;
19481 auto session = CreateSession(&session_deps_);
19482 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19483 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219484 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419485 }
19486
19487 protected:
19488 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419489
19490 private:
19491 TestReportingContext* test_reporting_context_;
19492};
19493
19494TEST_F(HttpNetworkTransactionReportingTest,
19495 DontProcessReportToHeaderNoService) {
19496 base::HistogramTester histograms;
19497 clear_reporting_service();
19498 RequestPolicy();
19499 histograms.ExpectBucketCount(
19500 ReportingHeaderParser::kHeaderOutcomeHistogram,
19501 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
19502}
19503
19504TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
19505 base::HistogramTester histograms;
19506 url_ = "http://www.example.org/";
19507 RequestPolicy();
19508 histograms.ExpectBucketCount(
19509 ReportingHeaderParser::kHeaderOutcomeHistogram,
19510 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19511}
19512
19513TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19514 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419515 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019516 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419517 reporting_context()->cache()->GetEndpointForTesting(
Lily Chenad5dd0802020-03-10 21:58:0919518 ReportingEndpointGroupKey(
19519 NetworkIsolationKey(),
19520 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
Lily Chenefb6fcf2019-04-19 04:17:5419521 GURL("https://www.example.org/upload/"));
19522 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419523}
19524
19525TEST_F(HttpNetworkTransactionReportingTest,
19526 DontProcessReportToHeaderInvalidHttps) {
19527 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219528 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19529 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1419530 histograms.ExpectBucketCount(
19531 ReportingHeaderParser::kHeaderOutcomeHistogram,
19532 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
19533}
19534#endif // BUILDFLAG(ENABLE_REPORTING)
19535
19536//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219537// Network Error Logging tests
19538
19539#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219540namespace {
19541
19542const char kUserAgent[] = "Mozilla/1.0";
19543const char kReferrer[] = "https://www.referrer.org/";
19544
19545} // namespace
19546
Douglas Creager3cb042052018-11-06 23:08:5219547class HttpNetworkTransactionNetworkErrorLoggingTest
19548 : public HttpNetworkTransactionTest {
19549 protected:
19550 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619551 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219552 auto network_error_logging_service =
19553 std::make_unique<TestNetworkErrorLoggingService>();
19554 test_network_error_logging_service_ = network_error_logging_service.get();
19555 session_deps_.network_error_logging_service =
19556 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219557
19558 extra_headers_.SetHeader("User-Agent", kUserAgent);
19559 extra_headers_.SetHeader("Referer", kReferrer);
19560
19561 request_.method = "GET";
19562 request_.url = GURL(url_);
19563 request_.extra_headers = extra_headers_;
19564 request_.reporting_upload_depth = reporting_upload_depth_;
19565 request_.traffic_annotation =
19566 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219567 }
19568
19569 TestNetworkErrorLoggingService* network_error_logging_service() const {
19570 return test_network_error_logging_service_;
19571 }
19572
19573 void clear_network_error_logging_service() {
19574 session_deps_.network_error_logging_service.reset();
19575 test_network_error_logging_service_ = nullptr;
19576 }
19577
19578 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219579 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619580 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319581 MockWrite data_writes[] = {
19582 MockWrite("GET / HTTP/1.1\r\n"
19583 "Host: www.example.org\r\n"
19584 "Connection: keep-alive\r\n"),
19585 MockWrite(ASYNC, extra_header_string.data(),
19586 extra_header_string.size()),
19587 };
Lily Chend3930e72019-03-01 19:31:1119588 MockRead data_reads[] = {
19589 MockRead("HTTP/1.0 200 OK\r\n"),
19590 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19591 MockRead("\r\n"),
19592 MockRead("hello world"),
19593 MockRead(SYNCHRONOUS, OK),
19594 };
Douglas Creager3cb042052018-11-06 23:08:5219595
Lily Chenfec60d92019-01-24 01:16:4219596 StaticSocketDataProvider reads(data_reads, data_writes);
19597 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219598
19599 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219600 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219601 ssl.ssl_info.cert =
19602 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19603 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219604 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19606 }
19607
Douglas Creager3cb042052018-11-06 23:08:5219608 TestCompletionCallback callback;
19609 auto session = CreateSession(&session_deps_);
19610 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219611 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19612 EXPECT_THAT(callback.GetResult(rv), IsOk());
19613
19614 std::string response_data;
19615 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19616 EXPECT_EQ("hello world", response_data);
19617 }
19618
19619 void CheckReport(size_t index,
19620 int status_code,
19621 int error_type,
19622 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19623 ASSERT_LT(index, network_error_logging_service()->errors().size());
19624
19625 const NetworkErrorLoggingService::RequestDetails& error =
19626 network_error_logging_service()->errors()[index];
19627 EXPECT_EQ(url_, error.uri);
19628 EXPECT_EQ(kReferrer, error.referrer);
19629 EXPECT_EQ(kUserAgent, error.user_agent);
19630 EXPECT_EQ(server_ip, error.server_ip);
19631 EXPECT_EQ("http/1.1", error.protocol);
19632 EXPECT_EQ("GET", error.method);
19633 EXPECT_EQ(status_code, error.status_code);
19634 EXPECT_EQ(error_type, error.type);
19635 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219636 }
19637
19638 protected:
19639 std::string url_ = "https://www.example.org/";
19640 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219641 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619642 HttpRequestHeaders extra_headers_;
19643 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219644
19645 private:
19646 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19647};
19648
19649TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19650 DontProcessNelHeaderNoService) {
19651 base::HistogramTester histograms;
19652 clear_network_error_logging_service();
19653 RequestPolicy();
19654 histograms.ExpectBucketCount(
19655 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19656 NetworkErrorLoggingService::HeaderOutcome::
19657 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
19658 1);
19659}
19660
19661TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19662 DontProcessNelHeaderHttp) {
19663 base::HistogramTester histograms;
19664 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219665 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219666 RequestPolicy();
19667 histograms.ExpectBucketCount(
19668 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19669 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19670}
19671
Lily Chen90ae93cc2019-02-14 01:15:3919672// Don't set NEL policies received on a proxied connection.
19673TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19674 DontProcessNelHeaderProxy) {
19675 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619676 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3919677 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1419678 RecordingBoundTestNetLog log;
Lily Chen90ae93cc2019-02-14 01:15:3919679 session_deps_.net_log = log.bound().net_log();
19680 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19681
19682 HttpRequestInfo request;
19683 request.method = "GET";
19684 request.url = GURL("https://www.example.org/");
19685 request.traffic_annotation =
19686 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19687
19688 // Since we have proxy, should try to establish tunnel.
19689 MockWrite data_writes1[] = {
19690 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19691 "Host: www.example.org:443\r\n"
19692 "Proxy-Connection: keep-alive\r\n\r\n"),
19693
19694 MockWrite("GET / HTTP/1.1\r\n"
19695 "Host: www.example.org\r\n"
19696 "Connection: keep-alive\r\n\r\n"),
19697 };
19698
19699 MockRead data_reads1[] = {
19700 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19701
19702 MockRead("HTTP/1.1 200 OK\r\n"),
19703 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19704 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19705 MockRead("Content-Length: 100\r\n\r\n"),
19706 MockRead(SYNCHRONOUS, OK),
19707 };
19708
19709 StaticSocketDataProvider data1(data_reads1, data_writes1);
19710 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19711 SSLSocketDataProvider ssl(ASYNC, OK);
19712 ssl.ssl_info.cert =
19713 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19714 ASSERT_TRUE(ssl.ssl_info.cert);
19715 ssl.ssl_info.cert_status = 0;
19716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19717
19718 TestCompletionCallback callback1;
19719 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19720
19721 int rv = trans.Start(&request, callback1.callback(), log.bound());
19722 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19723
19724 rv = callback1.WaitForResult();
19725 EXPECT_THAT(rv, IsOk());
19726
19727 const HttpResponseInfo* response = trans.GetResponseInfo();
19728 ASSERT_TRUE(response);
19729 EXPECT_EQ(200, response->headers->response_code());
19730 EXPECT_TRUE(response->was_fetched_via_proxy);
19731
19732 // No NEL header was set.
19733 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19734}
19735
Douglas Creager3cb042052018-11-06 23:08:5219736TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19737 RequestPolicy();
19738 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19739 const auto& header = network_error_logging_service()->headers()[0];
19740 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19741 header.origin);
19742 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19743 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19744}
19745
19746TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19747 DontProcessNelHeaderInvalidHttps) {
19748 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219749 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19750 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5219751 histograms.ExpectBucketCount(
19752 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19753 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
19754 1);
19755}
Douglas Creageref5eecdc2018-11-09 20:50:3619756
Lily Chenfec60d92019-01-24 01:16:4219757TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3619758 RequestPolicy();
19759 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219760 CheckReport(0 /* index */, 200 /* status_code */, OK);
19761}
19762
19763TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19764 CreateReportErrorAfterStart) {
19765 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19766 auto trans =
19767 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19768
19769 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
19770 StaticSocketDataProvider data;
19771 data.set_connect_data(mock_connect);
19772 session_deps_.socket_factory->AddSocketDataProvider(&data);
19773
19774 TestCompletionCallback callback;
19775
19776 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19777 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19778
19779 trans.reset();
19780
19781 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19782 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19783 IPAddress() /* server_ip */);
19784}
19785
19786// Same as above except the error is ASYNC
19787TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19788 CreateReportErrorAfterStartAsync) {
19789 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19790 auto trans =
19791 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19792
19793 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
19794 StaticSocketDataProvider data;
19795 data.set_connect_data(mock_connect);
19796 session_deps_.socket_factory->AddSocketDataProvider(&data);
19797
19798 TestCompletionCallback callback;
19799
19800 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19801 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19802
19803 trans.reset();
19804
19805 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19806 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19807 IPAddress() /* server_ip */);
19808}
19809
19810TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19811 CreateReportReadBodyError) {
19812 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319813 MockWrite data_writes[] = {
19814 MockWrite("GET / HTTP/1.1\r\n"
19815 "Host: www.example.org\r\n"
19816 "Connection: keep-alive\r\n"),
19817 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19818 };
Lily Chend3930e72019-03-01 19:31:1119819 MockRead data_reads[] = {
19820 MockRead("HTTP/1.0 200 OK\r\n"),
19821 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19822 MockRead("hello world"),
19823 MockRead(SYNCHRONOUS, OK),
19824 };
Lily Chenfec60d92019-01-24 01:16:4219825
19826 StaticSocketDataProvider reads(data_reads, data_writes);
19827 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19828
19829 SSLSocketDataProvider ssl(ASYNC, OK);
19830 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19831
19832 // Log start time
19833 base::TimeTicks start_time = base::TimeTicks::Now();
19834
19835 TestCompletionCallback callback;
19836 auto session = CreateSession(&session_deps_);
19837 auto trans =
19838 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19839 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19840 EXPECT_THAT(callback.GetResult(rv), IsOk());
19841
19842 const HttpResponseInfo* response = trans->GetResponseInfo();
19843 ASSERT_TRUE(response);
19844
19845 EXPECT_TRUE(response->headers);
19846 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19847
19848 std::string response_data;
19849 rv = ReadTransaction(trans.get(), &response_data);
19850 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19851
19852 trans.reset();
19853
19854 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19855
19856 CheckReport(0 /* index */, 200 /* status_code */,
19857 ERR_CONTENT_LENGTH_MISMATCH);
19858 const NetworkErrorLoggingService::RequestDetails& error =
19859 network_error_logging_service()->errors()[0];
19860 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19861}
19862
19863// Same as above except the final read is ASYNC.
19864TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19865 CreateReportReadBodyErrorAsync) {
19866 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319867 MockWrite data_writes[] = {
19868 MockWrite("GET / HTTP/1.1\r\n"
19869 "Host: www.example.org\r\n"
19870 "Connection: keep-alive\r\n"),
19871 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19872 };
Lily Chend3930e72019-03-01 19:31:1119873 MockRead data_reads[] = {
19874 MockRead("HTTP/1.0 200 OK\r\n"),
19875 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19876 MockRead("hello world"),
19877 MockRead(ASYNC, OK),
19878 };
Lily Chenfec60d92019-01-24 01:16:4219879
19880 StaticSocketDataProvider reads(data_reads, data_writes);
19881 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19882
19883 SSLSocketDataProvider ssl(ASYNC, OK);
19884 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19885
19886 // Log start time
19887 base::TimeTicks start_time = base::TimeTicks::Now();
19888
19889 TestCompletionCallback callback;
19890 auto session = CreateSession(&session_deps_);
19891 auto trans =
19892 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19893 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19894 EXPECT_THAT(callback.GetResult(rv), IsOk());
19895
19896 const HttpResponseInfo* response = trans->GetResponseInfo();
19897 ASSERT_TRUE(response);
19898
19899 EXPECT_TRUE(response->headers);
19900 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19901
19902 std::string response_data;
19903 rv = ReadTransaction(trans.get(), &response_data);
19904 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19905
19906 trans.reset();
19907
19908 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19909
19910 CheckReport(0 /* index */, 200 /* status_code */,
19911 ERR_CONTENT_LENGTH_MISMATCH);
19912 const NetworkErrorLoggingService::RequestDetails& error =
19913 network_error_logging_service()->errors()[0];
19914 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19915}
19916
19917TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19918 CreateReportRestartWithAuth) {
19919 std::string extra_header_string = extra_headers_.ToString();
19920 static const base::TimeDelta kSleepDuration =
19921 base::TimeDelta::FromMilliseconds(10);
19922
19923 MockWrite data_writes1[] = {
19924 MockWrite("GET / HTTP/1.1\r\n"
19925 "Host: www.example.org\r\n"
19926 "Connection: keep-alive\r\n"),
19927 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19928 };
19929
19930 MockRead data_reads1[] = {
19931 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19932 // Give a couple authenticate options (only the middle one is actually
19933 // supported).
19934 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19935 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19936 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19938 // Large content-length -- won't matter, as connection will be reset.
19939 MockRead("Content-Length: 10000\r\n\r\n"),
19940 MockRead(SYNCHRONOUS, ERR_FAILED),
19941 };
19942
19943 // After calling trans->RestartWithAuth(), this is the request we should
19944 // be issuing -- the final header line contains the credentials.
19945 MockWrite data_writes2[] = {
19946 MockWrite("GET / HTTP/1.1\r\n"
19947 "Host: www.example.org\r\n"
19948 "Connection: keep-alive\r\n"
19949 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19950 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19951 };
19952
19953 // Lastly, the server responds with the actual content.
19954 MockRead data_reads2[] = {
19955 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19956 MockRead("hello world"),
19957 MockRead(SYNCHRONOUS, OK),
19958 };
19959
19960 StaticSocketDataProvider data1(data_reads1, data_writes1);
19961 StaticSocketDataProvider data2(data_reads2, data_writes2);
19962 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19963 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19964
19965 SSLSocketDataProvider ssl1(ASYNC, OK);
19966 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19967 SSLSocketDataProvider ssl2(ASYNC, OK);
19968 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19969
19970 base::TimeTicks start_time = base::TimeTicks::Now();
19971 base::TimeTicks restart_time;
19972
19973 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19974 auto trans =
19975 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19976
19977 TestCompletionCallback callback1;
19978
19979 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19980 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19981
19982 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19983
19984 TestCompletionCallback callback2;
19985
19986 // Wait 10 ms then restart with auth
19987 FastForwardBy(kSleepDuration);
19988 restart_time = base::TimeTicks::Now();
19989 rv =
19990 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19991 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19992
19993 std::string response_data;
19994 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19995 EXPECT_EQ("hello world", response_data);
19996
19997 trans.reset();
19998
19999 // One 401 report for the auth challenge, then a 200 report for the successful
20000 // retry. Note that we don't report the error draining the body, as the first
20001 // request already generated a report for the auth challenge.
20002 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20003
20004 // Check error report contents
20005 CheckReport(0 /* index */, 401 /* status_code */, OK);
20006 CheckReport(1 /* index */, 200 /* status_code */, OK);
20007
20008 const NetworkErrorLoggingService::RequestDetails& error1 =
20009 network_error_logging_service()->errors()[0];
20010 const NetworkErrorLoggingService::RequestDetails& error2 =
20011 network_error_logging_service()->errors()[1];
20012
20013 // Sanity-check elapsed time values
20014 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20015 // Check that the start time is refreshed when restarting with auth.
20016 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20017}
20018
20019// Same as above, except draining the body before restarting fails
20020// asynchronously.
20021TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20022 CreateReportRestartWithAuthAsync) {
20023 std::string extra_header_string = extra_headers_.ToString();
20024 static const base::TimeDelta kSleepDuration =
20025 base::TimeDelta::FromMilliseconds(10);
20026
20027 MockWrite data_writes1[] = {
20028 MockWrite("GET / HTTP/1.1\r\n"
20029 "Host: www.example.org\r\n"
20030 "Connection: keep-alive\r\n"),
20031 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20032 };
20033
20034 MockRead data_reads1[] = {
20035 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20036 // Give a couple authenticate options (only the middle one is actually
20037 // supported).
20038 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20039 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20040 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20041 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20042 // Large content-length -- won't matter, as connection will be reset.
20043 MockRead("Content-Length: 10000\r\n\r\n"),
20044 MockRead(ASYNC, ERR_FAILED),
20045 };
20046
20047 // After calling trans->RestartWithAuth(), this is the request we should
20048 // be issuing -- the final header line contains the credentials.
20049 MockWrite data_writes2[] = {
20050 MockWrite("GET / HTTP/1.1\r\n"
20051 "Host: www.example.org\r\n"
20052 "Connection: keep-alive\r\n"
20053 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20054 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20055 };
20056
20057 // Lastly, the server responds with the actual content.
20058 MockRead data_reads2[] = {
20059 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20060 MockRead("hello world"),
20061 MockRead(SYNCHRONOUS, OK),
20062 };
20063
20064 StaticSocketDataProvider data1(data_reads1, data_writes1);
20065 StaticSocketDataProvider data2(data_reads2, data_writes2);
20066 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20067 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20068
20069 SSLSocketDataProvider ssl1(ASYNC, OK);
20070 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20071 SSLSocketDataProvider ssl2(ASYNC, OK);
20072 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20073
20074 base::TimeTicks start_time = base::TimeTicks::Now();
20075 base::TimeTicks restart_time;
20076
20077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20078 auto trans =
20079 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20080
20081 TestCompletionCallback callback1;
20082
20083 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20084 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20085
20086 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20087
20088 TestCompletionCallback callback2;
20089
20090 // Wait 10 ms then restart with auth
20091 FastForwardBy(kSleepDuration);
20092 restart_time = base::TimeTicks::Now();
20093 rv =
20094 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20095 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20096
20097 std::string response_data;
20098 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20099 EXPECT_EQ("hello world", response_data);
20100
20101 trans.reset();
20102
20103 // One 401 report for the auth challenge, then a 200 report for the successful
20104 // retry. Note that we don't report the error draining the body, as the first
20105 // request already generated a report for the auth challenge.
20106 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20107
20108 // Check error report contents
20109 CheckReport(0 /* index */, 401 /* status_code */, OK);
20110 CheckReport(1 /* index */, 200 /* status_code */, OK);
20111
20112 const NetworkErrorLoggingService::RequestDetails& error1 =
20113 network_error_logging_service()->errors()[0];
20114 const NetworkErrorLoggingService::RequestDetails& error2 =
20115 network_error_logging_service()->errors()[1];
20116
20117 // Sanity-check elapsed time values
20118 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20119 // Check that the start time is refreshed when restarting with auth.
20120 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20121}
20122
20123TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20124 CreateReportRetryKeepAliveConnectionReset) {
20125 std::string extra_header_string = extra_headers_.ToString();
20126 MockWrite data_writes1[] = {
20127 MockWrite("GET / HTTP/1.1\r\n"
20128 "Host: www.example.org\r\n"
20129 "Connection: keep-alive\r\n"),
20130 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20131 MockWrite("GET / HTTP/1.1\r\n"
20132 "Host: www.example.org\r\n"
20133 "Connection: keep-alive\r\n"),
20134 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20135 };
20136
20137 MockRead data_reads1[] = {
20138 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20139 MockRead("hello"),
20140 // Connection is reset
20141 MockRead(ASYNC, ERR_CONNECTION_RESET),
20142 };
20143
20144 // Successful retry
20145 MockRead data_reads2[] = {
20146 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20147 MockRead("world"),
20148 MockRead(ASYNC, OK),
20149 };
20150
20151 StaticSocketDataProvider data1(data_reads1, data_writes1);
20152 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20153 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20154 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20155
20156 SSLSocketDataProvider ssl1(ASYNC, OK);
20157 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20158 SSLSocketDataProvider ssl2(ASYNC, OK);
20159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20160
20161 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20162 auto trans1 =
20163 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20164
20165 TestCompletionCallback callback1;
20166
20167 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20168 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20169
20170 std::string response_data;
20171 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20172 EXPECT_EQ("hello", response_data);
20173
20174 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20175
20176 auto trans2 =
20177 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20178
20179 TestCompletionCallback callback2;
20180
20181 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20182 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20183
20184 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20185 EXPECT_EQ("world", response_data);
20186
20187 trans1.reset();
20188 trans2.reset();
20189
20190 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20191 // the second request, then an OK report from the successful retry.
20192 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20193
20194 // Check error report contents
20195 CheckReport(0 /* index */, 200 /* status_code */, OK);
20196 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20197 CheckReport(2 /* index */, 200 /* status_code */, OK);
20198}
20199
20200TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20201 CreateReportRetryKeepAlive408) {
20202 std::string extra_header_string = extra_headers_.ToString();
20203 MockWrite data_writes1[] = {
20204 MockWrite("GET / HTTP/1.1\r\n"
20205 "Host: www.example.org\r\n"
20206 "Connection: keep-alive\r\n"),
20207 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20208 MockWrite("GET / HTTP/1.1\r\n"
20209 "Host: www.example.org\r\n"
20210 "Connection: keep-alive\r\n"),
20211 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20212 };
20213
20214 MockRead data_reads1[] = {
20215 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20216 MockRead("hello"),
20217 // 408 Request Timeout
20218 MockRead(SYNCHRONOUS,
20219 "HTTP/1.1 408 Request Timeout\r\n"
20220 "Connection: Keep-Alive\r\n"
20221 "Content-Length: 6\r\n\r\n"
20222 "Pickle"),
20223 };
20224
20225 // Successful retry
20226 MockRead data_reads2[] = {
20227 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20228 MockRead("world"),
20229 MockRead(ASYNC, OK),
20230 };
20231
20232 StaticSocketDataProvider data1(data_reads1, data_writes1);
20233 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20234 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20235 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20236
20237 SSLSocketDataProvider ssl1(ASYNC, OK);
20238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20239 SSLSocketDataProvider ssl2(ASYNC, OK);
20240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20241
20242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20243 auto trans1 =
20244 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20245
20246 TestCompletionCallback callback1;
20247
20248 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20249 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20250
20251 std::string response_data;
20252 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20253 EXPECT_EQ("hello", response_data);
20254
20255 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20256
20257 auto trans2 =
20258 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20259
20260 TestCompletionCallback callback2;
20261
20262 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20263 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20264
20265 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20266 EXPECT_EQ("world", response_data);
20267
20268 trans1.reset();
20269 trans2.reset();
20270
20271 // One 200 report from first request, then a 408 report from
20272 // the second request, then a 200 report from the successful retry.
20273 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20274
20275 // Check error report contents
20276 CheckReport(0 /* index */, 200 /* status_code */, OK);
20277 CheckReport(1 /* index */, 408 /* status_code */, OK);
20278 CheckReport(2 /* index */, 200 /* status_code */, OK);
20279}
20280
20281TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20282 CreateReportRetry421WithoutConnectionPooling) {
20283 // Two hosts resolve to the same IP address.
20284 const std::string ip_addr = "1.2.3.4";
20285 IPAddress ip;
20286 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20287 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20288
20289 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20290 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20291 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20292
20293 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20294
20295 // Two requests on the first connection.
20296 spdy::SpdySerializedFrame req1(
20297 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20298 spdy_util_.UpdateWithStreamDestruction(1);
20299 spdy::SpdySerializedFrame req2(
20300 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20301 spdy::SpdySerializedFrame rst(
20302 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20303 MockWrite writes1[] = {
20304 CreateMockWrite(req1, 0),
20305 CreateMockWrite(req2, 3),
20306 CreateMockWrite(rst, 6),
20307 };
20308
20309 // The first one succeeds, the second gets error 421 Misdirected Request.
20310 spdy::SpdySerializedFrame resp1(
20311 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20312 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20313 spdy::SpdyHeaderBlock response_headers;
20314 response_headers[spdy::kHttp2StatusHeader] = "421";
20315 spdy::SpdySerializedFrame resp2(
20316 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20317 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20318 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20319
20320 MockConnect connect1(ASYNC, OK, peer_addr);
20321 SequencedSocketData data1(connect1, reads1, writes1);
20322 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20323
20324 AddSSLSocketData();
20325
20326 // Retry the second request on a second connection.
20327 SpdyTestUtil spdy_util2;
20328 spdy::SpdySerializedFrame req3(
20329 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20330 MockWrite writes2[] = {
20331 CreateMockWrite(req3, 0),
20332 };
20333
20334 spdy::SpdySerializedFrame resp3(
20335 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20336 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20337 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20338 MockRead(ASYNC, 0, 3)};
20339
20340 MockConnect connect2(ASYNC, OK, peer_addr);
20341 SequencedSocketData data2(connect2, reads2, writes2);
20342 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20343
20344 AddSSLSocketData();
20345
20346 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320347 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320348 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20349 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320350 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220351
20352 HttpRequestInfo request1;
20353 request1.method = "GET";
20354 request1.url = GURL("https://www.example.org/");
20355 request1.load_flags = 0;
20356 request1.traffic_annotation =
20357 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20358 auto trans1 =
20359 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20360
Eric Orthf4db66a2019-02-19 21:35:3320361 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220362 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20363 EXPECT_THAT(callback.GetResult(rv), IsOk());
20364
20365 const HttpResponseInfo* response = trans1->GetResponseInfo();
20366 ASSERT_TRUE(response);
20367 ASSERT_TRUE(response->headers);
20368 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20369 EXPECT_TRUE(response->was_fetched_via_spdy);
20370 EXPECT_TRUE(response->was_alpn_negotiated);
20371 std::string response_data;
20372 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20373 EXPECT_EQ("hello!", response_data);
20374
20375 trans1.reset();
20376
20377 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20378
20379 HttpRequestInfo request2;
20380 request2.method = "GET";
20381 request2.url = GURL("https://mail.example.org/");
20382 request2.load_flags = 0;
20383 request2.traffic_annotation =
20384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20385 auto trans2 =
20386 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20387
Matt Muellerd9342e3a2019-11-26 01:41:1420388 RecordingBoundTestNetLog log;
Lily Chenfec60d92019-01-24 01:16:4220389 rv = trans2->Start(&request2, callback.callback(), log.bound());
20390 EXPECT_THAT(callback.GetResult(rv), IsOk());
20391
20392 response = trans2->GetResponseInfo();
20393 ASSERT_TRUE(response);
20394 ASSERT_TRUE(response->headers);
20395 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20396 EXPECT_TRUE(response->was_fetched_via_spdy);
20397 EXPECT_TRUE(response->was_alpn_negotiated);
20398 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20399 EXPECT_EQ("hello!", response_data);
20400
20401 trans2.reset();
20402
20403 // One 200 report from the first request, then a 421 report from the
20404 // second request, then a 200 report from the successful retry.
20405 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20406
20407 // Check error report contents
20408 const NetworkErrorLoggingService::RequestDetails& error1 =
20409 network_error_logging_service()->errors()[0];
20410 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20411 EXPECT_TRUE(error1.referrer.is_empty());
20412 EXPECT_EQ("", error1.user_agent);
20413 EXPECT_EQ(ip, error1.server_ip);
20414 EXPECT_EQ("h2", error1.protocol);
20415 EXPECT_EQ("GET", error1.method);
20416 EXPECT_EQ(200, error1.status_code);
20417 EXPECT_EQ(OK, error1.type);
20418 EXPECT_EQ(0, error1.reporting_upload_depth);
20419
20420 const NetworkErrorLoggingService::RequestDetails& error2 =
20421 network_error_logging_service()->errors()[1];
20422 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20423 EXPECT_TRUE(error2.referrer.is_empty());
20424 EXPECT_EQ("", error2.user_agent);
20425 EXPECT_EQ(ip, error2.server_ip);
20426 EXPECT_EQ("h2", error2.protocol);
20427 EXPECT_EQ("GET", error2.method);
20428 EXPECT_EQ(421, error2.status_code);
20429 EXPECT_EQ(OK, error2.type);
20430 EXPECT_EQ(0, error2.reporting_upload_depth);
20431
20432 const NetworkErrorLoggingService::RequestDetails& error3 =
20433 network_error_logging_service()->errors()[2];
20434 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20435 EXPECT_TRUE(error3.referrer.is_empty());
20436 EXPECT_EQ("", error3.user_agent);
20437 EXPECT_EQ(ip, error3.server_ip);
20438 EXPECT_EQ("h2", error3.protocol);
20439 EXPECT_EQ("GET", error3.method);
20440 EXPECT_EQ(200, error3.status_code);
20441 EXPECT_EQ(OK, error3.type);
20442 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620443}
20444
Lily Chend3930e72019-03-01 19:31:1120445TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20446 CreateReportCancelAfterStart) {
20447 StaticSocketDataProvider data;
20448 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20449 session_deps_.socket_factory->AddSocketDataProvider(&data);
20450
20451 TestCompletionCallback callback;
20452 auto session = CreateSession(&session_deps_);
20453 auto trans =
20454 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20455 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20456 EXPECT_EQ(rv, ERR_IO_PENDING);
20457
20458 // Cancel after start.
20459 trans.reset();
20460
20461 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20462 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20463 IPAddress() /* server_ip */);
20464}
20465
20466TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20467 CreateReportCancelBeforeReadingBody) {
20468 std::string extra_header_string = extra_headers_.ToString();
20469 MockWrite data_writes[] = {
20470 MockWrite("GET / HTTP/1.1\r\n"
20471 "Host: www.example.org\r\n"
20472 "Connection: keep-alive\r\n"),
20473 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20474 };
20475 MockRead data_reads[] = {
20476 MockRead("HTTP/1.0 200 OK\r\n"),
20477 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20478 };
20479
20480 StaticSocketDataProvider data(data_reads, data_writes);
20481 session_deps_.socket_factory->AddSocketDataProvider(&data);
20482
20483 SSLSocketDataProvider ssl(ASYNC, OK);
20484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20485
20486 TestCompletionCallback callback;
20487 auto session = CreateSession(&session_deps_);
20488 auto trans =
20489 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20490 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20491 EXPECT_THAT(callback.GetResult(rv), IsOk());
20492
20493 const HttpResponseInfo* response = trans->GetResponseInfo();
20494 ASSERT_TRUE(response);
20495
20496 EXPECT_TRUE(response->headers);
20497 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20498
20499 // Cancel before reading the body.
20500 trans.reset();
20501
20502 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20503 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20504}
20505
Lily Chen00196ab62018-12-04 19:52:2920506TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
Lily Chen00196ab62018-12-04 19:52:2920507 RequestPolicy();
20508 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20509 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20510
20511 // Make HTTP request
20512 std::string extra_header_string = extra_headers_.ToString();
20513 MockRead data_reads[] = {
20514 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20515 MockRead("hello world"),
20516 MockRead(SYNCHRONOUS, OK),
20517 };
20518 MockWrite data_writes[] = {
20519 MockWrite("GET / HTTP/1.1\r\n"
20520 "Host: www.example.org\r\n"
20521 "Connection: keep-alive\r\n"),
20522 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20523 };
20524
Lily Chend3930e72019-03-01 19:31:1120525 StaticSocketDataProvider data(data_reads, data_writes);
20526 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920527
Lily Chenfec60d92019-01-24 01:16:4220528 // Insecure url
20529 url_ = "http://www.example.org/";
20530 request_.url = GURL(url_);
20531
Lily Chen00196ab62018-12-04 19:52:2920532 TestCompletionCallback callback;
20533 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220534 auto trans =
20535 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20536 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20537 EXPECT_THAT(callback.GetResult(rv), IsOk());
20538
20539 std::string response_data;
20540 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20541 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920542
20543 // Insecure request does not generate a report
Lily Chen00196ab62018-12-04 19:52:2920544 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20545}
20546
20547TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20548 DontCreateReportHttpError) {
Lily Chen00196ab62018-12-04 19:52:2920549 RequestPolicy();
20550 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20551 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20552
20553 // Make HTTP request that fails
20554 MockRead data_reads[] = {
20555 MockRead("hello world"),
20556 MockRead(SYNCHRONOUS, OK),
20557 };
20558
20559 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20560 session_deps_.socket_factory->AddSocketDataProvider(&data);
20561
Lily Chenfec60d92019-01-24 01:16:4220562 url_ = "http://www.originwithoutpolicy.com:2000/";
20563 request_.url = GURL(url_);
20564
Lily Chen00196ab62018-12-04 19:52:2920565 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20566
Lily Chen00196ab62018-12-04 19:52:2920567 auto trans =
20568 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920569 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220570 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920571 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20572
20573 // Insecure request does not generate a report, regardless of existence of a
20574 // policy for the origin.
Lily Chen00196ab62018-12-04 19:52:2920575 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20576}
20577
Lily Chen90ae93cc2019-02-14 01:15:3920578// Don't report on proxy auth challenges, don't report if connecting through a
20579// proxy.
20580TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20581 HttpRequestInfo request;
20582 request.method = "GET";
20583 request.url = GURL("https://www.example.org/");
20584 request.traffic_annotation =
20585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20586
20587 // Configure against proxy server "myproxy:70".
20588 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620589 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920590 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20591 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20592
20593 // Since we have proxy, should try to establish tunnel.
20594 MockWrite data_writes1[] = {
20595 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20596 "Host: www.example.org:443\r\n"
20597 "Proxy-Connection: keep-alive\r\n\r\n"),
20598 };
20599
20600 // The proxy responds to the connect with a 407, using a non-persistent
20601 // connection.
20602 MockRead data_reads1[] = {
20603 // No credentials.
20604 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20605 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20606 MockRead("Proxy-Connection: close\r\n\r\n"),
20607 };
20608
20609 MockWrite data_writes2[] = {
20610 // After calling trans->RestartWithAuth(), this is the request we should
20611 // be issuing -- the final header line contains the credentials.
20612 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20613 "Host: www.example.org:443\r\n"
20614 "Proxy-Connection: keep-alive\r\n"
20615 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20616
20617 MockWrite("GET / HTTP/1.1\r\n"
20618 "Host: www.example.org\r\n"
20619 "Connection: keep-alive\r\n\r\n"),
20620 };
20621
20622 MockRead data_reads2[] = {
20623 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20624
20625 MockRead("HTTP/1.1 200 OK\r\n"),
20626 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20627 MockRead("Content-Length: 5\r\n\r\n"),
20628 MockRead(SYNCHRONOUS, "hello"),
20629 };
20630
20631 StaticSocketDataProvider data1(data_reads1, data_writes1);
20632 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20633 StaticSocketDataProvider data2(data_reads2, data_writes2);
20634 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20635 SSLSocketDataProvider ssl(ASYNC, OK);
20636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20637
20638 TestCompletionCallback callback1;
20639
20640 auto trans =
20641 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20642
20643 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20644 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20645
20646 const HttpResponseInfo* response = trans->GetResponseInfo();
20647 EXPECT_EQ(407, response->headers->response_code());
20648
20649 std::string response_data;
20650 rv = ReadTransaction(trans.get(), &response_data);
20651 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20652
20653 // No NEL report is generated for the 407.
20654 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20655
20656 TestCompletionCallback callback2;
20657
20658 rv =
20659 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20660 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20661
20662 response = trans->GetResponseInfo();
20663 EXPECT_EQ(200, response->headers->response_code());
20664
20665 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20666 EXPECT_EQ("hello", response_data);
20667
20668 trans.reset();
20669
20670 // No NEL report is generated because we are behind a proxy.
20671 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20672}
20673
Douglas Creageref5eecdc2018-11-09 20:50:3620674TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20675 ReportContainsUploadDepth) {
20676 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220677 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620678 RequestPolicy();
20679 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220680 const NetworkErrorLoggingService::RequestDetails& error =
20681 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620682 EXPECT_EQ(7, error.reporting_upload_depth);
20683}
20684
Lily Chenfec60d92019-01-24 01:16:4220685TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20686 std::string extra_header_string = extra_headers_.ToString();
20687 static const base::TimeDelta kSleepDuration =
20688 base::TimeDelta::FromMilliseconds(10);
20689
20690 std::vector<MockWrite> data_writes = {
20691 MockWrite(ASYNC, 0,
20692 "GET / HTTP/1.1\r\n"
20693 "Host: www.example.org\r\n"
20694 "Connection: keep-alive\r\n"),
20695 MockWrite(ASYNC, 1, extra_header_string.data()),
20696 };
20697
20698 std::vector<MockRead> data_reads = {
20699 // Write one byte of the status line, followed by a pause.
20700 MockRead(ASYNC, 2, "H"),
20701 MockRead(ASYNC, ERR_IO_PENDING, 3),
20702 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20703 MockRead(ASYNC, 5, "hello world"),
20704 MockRead(SYNCHRONOUS, OK, 6),
20705 };
20706
20707 SequencedSocketData data(data_reads, data_writes);
20708 session_deps_.socket_factory->AddSocketDataProvider(&data);
20709
20710 SSLSocketDataProvider ssl(ASYNC, OK);
20711 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20712
20713 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20714
20715 auto trans =
20716 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20717
20718 TestCompletionCallback callback;
20719
20720 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20721 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20722
20723 data.RunUntilPaused();
20724 ASSERT_TRUE(data.IsPaused());
20725 FastForwardBy(kSleepDuration);
20726 data.Resume();
20727
20728 EXPECT_THAT(callback.GetResult(rv), IsOk());
20729
20730 std::string response_data;
20731 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20732 EXPECT_EQ("hello world", response_data);
20733
20734 trans.reset();
20735
Douglas Creageref5eecdc2018-11-09 20:50:3620736 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220737
20738 CheckReport(0 /* index */, 200 /* status_code */, OK);
20739
20740 const NetworkErrorLoggingService::RequestDetails& error =
20741 network_error_logging_service()->errors()[0];
20742
20743 // Sanity-check elapsed time in error report
20744 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620745}
Lily Chenfec60d92019-01-24 01:16:4220746
Douglas Creager3cb042052018-11-06 23:08:5220747#endif // BUILDFLAG(ENABLE_REPORTING)
20748
Batalov Vladislava4e97a502019-04-11 15:35:2320749TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20750 HttpRequestInfo request;
20751 request.method = "GET";
20752 request.url = GURL("http://example.org/");
20753
20754 request.load_flags = LOAD_ONLY_FROM_CACHE;
20755
20756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20757 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20758 TestCompletionCallback callback1;
20759 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
20760
20761 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
20762}
20763
Steven Valdez1c1859172019-04-10 15:33:2820764TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1520765 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820766 HttpRequestInfo request;
20767 request.method = "GET";
20768 request.url = GURL("https://www.example.org/");
20769 request.traffic_annotation =
20770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20771
20772 MockWrite data_writes[] = {
20773 MockWrite("GET / HTTP/1.1\r\n"
20774 "Host: www.example.org\r\n"
20775 "Connection: keep-alive\r\n\r\n"),
20776 };
20777
Steven Valdez1c1859172019-04-10 15:33:2820778 MockRead data_reads[] = {
20779 MockRead("HTTP/1.1 200 OK\r\n"),
20780 MockRead("Content-Length: 1\r\n\r\n"),
20781 MockRead(SYNCHRONOUS, "1"),
20782 };
20783
20784 StaticSocketDataProvider data(data_reads, data_writes);
20785 session_deps_.socket_factory->AddSocketDataProvider(&data);
20786 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520787 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820788 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520789 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820790 session_deps_.enable_early_data = true;
20791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20792
20793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20794
20795 TestCompletionCallback callback;
20796 auto trans =
20797 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20798
David Benjaminbae08ba2019-10-18 21:06:1520799 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820800 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20801 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20802
20803 rv = callback.WaitForResult();
20804 EXPECT_THAT(rv, IsOk());
20805
20806 const HttpResponseInfo* response = trans->GetResponseInfo();
20807 ASSERT_TRUE(response);
20808 ASSERT_TRUE(response->headers);
20809 EXPECT_EQ(200, response->headers->response_code());
20810 EXPECT_EQ(1, response->headers->GetContentLength());
20811
20812 // Check that ConfirmHandshake wasn't called.
20813 ASSERT_FALSE(ssl.ConfirmDataConsumed());
20814 ASSERT_TRUE(ssl.WriteBeforeConfirm());
20815
David Benjaminbae08ba2019-10-18 21:06:1520816 // The handshake time should include the time it took to run Connect(), but
20817 // not ConfirmHandshake().
20818 LoadTimingInfo load_timing_info;
20819 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20820 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20821 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20822 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20823 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20824
Steven Valdez1c1859172019-04-10 15:33:2820825 trans.reset();
20826
Matt Menke433de6d2020-03-04 00:24:1120827 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820828}
20829
20830TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520831 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820832 HttpRequestInfo request;
20833 request.method = "POST";
20834 request.url = GURL("https://www.example.org/");
20835 request.traffic_annotation =
20836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20837
20838 MockWrite data_writes[] = {
20839 MockWrite(SYNCHRONOUS,
20840 "POST / HTTP/1.1\r\n"
20841 "Host: www.example.org\r\n"
20842 "Connection: keep-alive\r\n"
20843 "Content-Length: 0\r\n\r\n"),
20844 };
20845
Steven Valdez1c1859172019-04-10 15:33:2820846 MockRead data_reads[] = {
20847 MockRead("HTTP/1.1 200 OK\r\n"),
20848 MockRead("Content-Length: 1\r\n\r\n"),
20849 MockRead(SYNCHRONOUS, "1"),
20850 };
20851
20852 StaticSocketDataProvider data(data_reads, data_writes);
20853 session_deps_.socket_factory->AddSocketDataProvider(&data);
20854 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520855 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820856 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520857 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820858 session_deps_.enable_early_data = true;
20859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20860
20861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20862
20863 TestCompletionCallback callback;
20864 auto trans =
20865 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20866
David Benjaminbae08ba2019-10-18 21:06:1520867 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820868 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20870
20871 rv = callback.WaitForResult();
20872 EXPECT_THAT(rv, IsOk());
20873
20874 const HttpResponseInfo* response = trans->GetResponseInfo();
20875 ASSERT_TRUE(response);
20876 ASSERT_TRUE(response->headers);
20877 EXPECT_EQ(200, response->headers->response_code());
20878 EXPECT_EQ(1, response->headers->GetContentLength());
20879
20880 // Check that the Write didn't get called before ConfirmHandshake completed.
20881 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20882
David Benjaminbae08ba2019-10-18 21:06:1520883 // The handshake time should include the time it took to run Connect(), but
20884 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
20885 // assume the connection did not negotiate 0-RTT or the handshake was already
20886 // confirmed.
20887 LoadTimingInfo load_timing_info;
20888 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20889 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20890 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20891 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20892 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20893
Steven Valdez1c1859172019-04-10 15:33:2820894 trans.reset();
20895
Matt Menke433de6d2020-03-04 00:24:1120896 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820897}
20898
20899TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20900 HttpRequestInfo request;
20901 request.method = "POST";
20902 request.url = GURL("https://www.example.org/");
20903 request.traffic_annotation =
20904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20905
20906 MockWrite data_writes[] = {
20907 MockWrite(ASYNC,
20908 "POST / HTTP/1.1\r\n"
20909 "Host: www.example.org\r\n"
20910 "Connection: keep-alive\r\n"
20911 "Content-Length: 0\r\n\r\n"),
20912 };
20913
Steven Valdez1c1859172019-04-10 15:33:2820914 MockRead data_reads[] = {
20915 MockRead("HTTP/1.1 200 OK\r\n"),
20916 MockRead("Content-Length: 1\r\n\r\n"),
20917 MockRead(SYNCHRONOUS, "1"),
20918 };
20919
20920 StaticSocketDataProvider data(data_reads, data_writes);
20921 session_deps_.socket_factory->AddSocketDataProvider(&data);
20922 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20923 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20924 session_deps_.enable_early_data = true;
20925 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20926
20927 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20928
20929 TestCompletionCallback callback;
20930 auto trans =
20931 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20932
20933 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20934 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20935
20936 rv = callback.WaitForResult();
20937 EXPECT_THAT(rv, IsOk());
20938
20939 const HttpResponseInfo* response = trans->GetResponseInfo();
20940 ASSERT_TRUE(response);
20941 ASSERT_TRUE(response->headers);
20942 EXPECT_EQ(200, response->headers->response_code());
20943 EXPECT_EQ(1, response->headers->GetContentLength());
20944
20945 // Check that the Write didn't get called before ConfirmHandshake completed.
20946 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20947
20948 trans.reset();
20949
Matt Menke433de6d2020-03-04 00:24:1120950 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820951}
20952
20953TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520954 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820955 HttpRequestInfo request;
20956 request.method = "POST";
20957 request.url = GURL("https://www.example.org/");
20958 request.traffic_annotation =
20959 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20960
20961 MockWrite data_writes[] = {
20962 MockWrite(SYNCHRONOUS,
20963 "POST / HTTP/1.1\r\n"
20964 "Host: www.example.org\r\n"
20965 "Connection: keep-alive\r\n"
20966 "Content-Length: 0\r\n\r\n"),
20967 };
20968
Steven Valdez1c1859172019-04-10 15:33:2820969 MockRead data_reads[] = {
20970 MockRead("HTTP/1.1 200 OK\r\n"),
20971 MockRead("Content-Length: 1\r\n\r\n"),
20972 MockRead(SYNCHRONOUS, "1"),
20973 };
20974
20975 StaticSocketDataProvider data(data_reads, data_writes);
20976 session_deps_.socket_factory->AddSocketDataProvider(&data);
20977 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520978 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820979 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1520980 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820981 session_deps_.enable_early_data = true;
20982 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20983
20984 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20985
20986 TestCompletionCallback callback;
20987 auto trans =
20988 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20989
David Benjaminbae08ba2019-10-18 21:06:1520990 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820991 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20992 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20993
20994 rv = callback.WaitForResult();
20995 EXPECT_THAT(rv, IsOk());
20996
20997 const HttpResponseInfo* response = trans->GetResponseInfo();
20998 ASSERT_TRUE(response);
20999 ASSERT_TRUE(response->headers);
21000 EXPECT_EQ(200, response->headers->response_code());
21001 EXPECT_EQ(1, response->headers->GetContentLength());
21002
21003 // Check that the Write didn't get called before ConfirmHandshake completed.
21004 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21005
David Benjaminbae08ba2019-10-18 21:06:1521006 // The handshake time should include the time it took to run Connect() and
21007 // ConfirmHandshake().
21008 LoadTimingInfo load_timing_info;
21009 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21010 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21011 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21012 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
21013 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
21014 start_time + 2 * kDelay);
21015
Steven Valdez1c1859172019-04-10 15:33:2821016 trans.reset();
21017
Matt Menke433de6d2020-03-04 00:24:1121018 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821019}
21020
21021TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
21022 HttpRequestInfo request;
21023 request.method = "POST";
21024 request.url = GURL("https://www.example.org/");
21025 request.traffic_annotation =
21026 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21027
21028 MockWrite data_writes[] = {
21029 MockWrite(ASYNC,
21030 "POST / HTTP/1.1\r\n"
21031 "Host: www.example.org\r\n"
21032 "Connection: keep-alive\r\n"
21033 "Content-Length: 0\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);
21045 ssl.confirm = MockConfirm(ASYNC, OK);
21046 session_deps_.enable_early_data = true;
21047 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21048
21049 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21050
21051 TestCompletionCallback callback;
21052 auto trans =
21053 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21054
21055 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21056 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21057
21058 rv = callback.WaitForResult();
21059 EXPECT_THAT(rv, IsOk());
21060
21061 const HttpResponseInfo* response = trans->GetResponseInfo();
21062 ASSERT_TRUE(response);
21063 ASSERT_TRUE(response->headers);
21064 EXPECT_EQ(200, response->headers->response_code());
21065 EXPECT_EQ(1, response->headers->GetContentLength());
21066
21067 // Check that the Write didn't get called before ConfirmHandshake completed.
21068 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21069
21070 trans.reset();
21071
Matt Menke433de6d2020-03-04 00:24:1121072 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821073}
21074
David Benjaminfb976932019-05-15 13:39:1521075// 0-RTT rejects are handled at HttpNetworkTransaction.
21076TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
21077 enum class RejectType {
21078 kRead,
21079 kWrite,
21080 kConfirm,
21081 };
21082
21083 for (RejectType type :
21084 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
21085 SCOPED_TRACE(static_cast<int>(type));
21086 for (Error reject_error :
21087 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
21088 SCOPED_TRACE(reject_error);
21089 session_deps_.socket_factory =
21090 std::make_unique<MockClientSocketFactory>();
21091
21092 HttpRequestInfo request;
21093 request.method = type == RejectType::kConfirm ? "POST" : "GET";
21094 request.url = GURL("https://www.example.org/");
21095 request.traffic_annotation =
21096 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21097
21098 // The first request fails.
21099 std::vector<MockWrite> data1_writes;
21100 std::vector<MockRead> data1_reads;
21101 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
21102 switch (type) {
21103 case RejectType::kRead:
21104 data1_writes.emplace_back(
21105 "GET / HTTP/1.1\r\n"
21106 "Host: www.example.org\r\n"
21107 "Connection: keep-alive\r\n\r\n");
21108 data1_reads.emplace_back(ASYNC, reject_error);
21109 // Cause ConfirmHandshake to hang (it should not be called).
21110 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21111 break;
21112 case RejectType::kWrite:
21113 data1_writes.emplace_back(ASYNC, reject_error);
21114 // Cause ConfirmHandshake to hang (it should not be called).
21115 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21116 break;
21117 case RejectType::kConfirm:
21118 // The request never gets far enough to read or write.
21119 ssl1.confirm = MockConfirm(ASYNC, reject_error);
21120 break;
21121 }
21122
21123 StaticSocketDataProvider data1(data1_reads, data1_writes);
21124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21125 session_deps_.enable_early_data = true;
21126 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21127
21128 // The retry succeeds.
21129 //
21130 // TODO(https://crbug.com/950705): If |reject_error| is
21131 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
21132 MockWrite data2_writes[] = {
21133 request.method == "POST"
21134 ? MockWrite("POST / HTTP/1.1\r\n"
21135 "Host: www.example.org\r\n"
21136 "Connection: keep-alive\r\n"
21137 "Content-Length: 0\r\n\r\n")
21138 : MockWrite("GET / HTTP/1.1\r\n"
21139 "Host: www.example.org\r\n"
21140 "Connection: keep-alive\r\n\r\n"),
21141 };
21142
21143 MockRead data2_reads[] = {
21144 MockRead("HTTP/1.1 200 OK\r\n"),
21145 MockRead("Content-Length: 1\r\n\r\n"),
21146 MockRead(SYNCHRONOUS, "1"),
21147 };
21148
21149 StaticSocketDataProvider data2(data2_reads, data2_writes);
21150 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21151 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21152 ssl2.confirm = MockConfirm(ASYNC, OK);
21153 session_deps_.enable_early_data = true;
21154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21155
21156 std::unique_ptr<HttpNetworkSession> session(
21157 CreateSession(&session_deps_));
21158
21159 TestCompletionCallback callback;
21160 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21161 session.get());
21162
21163 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21164 NetLogWithSource())),
21165 IsOk());
21166
21167 const HttpResponseInfo* response = trans->GetResponseInfo();
21168 ASSERT_TRUE(response);
21169 ASSERT_TRUE(response->headers);
21170 EXPECT_EQ(200, response->headers->response_code());
21171 EXPECT_EQ(1, response->headers->GetContentLength());
21172 }
21173 }
21174}
21175
Steven Valdez1c1859172019-04-10 15:33:2821176TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21177 HttpRequestInfo request;
21178 request.method = "POST";
21179 request.url = GURL("https://www.example.org/");
21180 request.traffic_annotation =
21181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21182
21183 MockWrite data_writes[] = {
21184 MockWrite("POST / HTTP/1.1\r\n"
21185 "Host: www.example.org\r\n"
21186 "Connection: keep-alive\r\n"
21187 "Content-Length: 0\r\n\r\n"),
21188 };
21189
Steven Valdez1c1859172019-04-10 15:33:2821190 MockRead data_reads[] = {
21191 MockRead("HTTP/1.1 200 OK\r\n"),
21192 MockRead("Content-Length: 1\r\n\r\n"),
21193 MockRead(SYNCHRONOUS, "1"),
21194 };
21195
21196 StaticSocketDataProvider data(data_reads, data_writes);
21197 session_deps_.socket_factory->AddSocketDataProvider(&data);
21198 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21199 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21200 session_deps_.enable_early_data = true;
21201 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21202
21203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21204
21205 TestCompletionCallback callback;
21206 auto trans =
21207 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21208
21209 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21211
21212 rv = callback.WaitForResult();
21213 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21214
21215 // Check that the Write didn't get called before ConfirmHandshake completed.
21216 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21217
21218 trans.reset();
21219
Matt Menke433de6d2020-03-04 00:24:1121220 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821221}
21222
21223TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21224 HttpRequestInfo request;
21225 request.method = "POST";
21226 request.url = GURL("https://www.example.org/");
21227 request.traffic_annotation =
21228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21229
21230 MockWrite data_writes[] = {
21231 MockWrite("POST / HTTP/1.1\r\n"
21232 "Host: www.example.org\r\n"
21233 "Connection: keep-alive\r\n"
21234 "Content-Length: 0\r\n\r\n"),
21235 };
21236
Steven Valdez1c1859172019-04-10 15:33:2821237 MockRead data_reads[] = {
21238 MockRead("HTTP/1.1 200 OK\r\n"),
21239 MockRead("Content-Length: 1\r\n\r\n"),
21240 MockRead(SYNCHRONOUS, "1"),
21241 };
21242
21243 StaticSocketDataProvider data(data_reads, data_writes);
21244 session_deps_.socket_factory->AddSocketDataProvider(&data);
21245 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21246 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21247 session_deps_.enable_early_data = true;
21248 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21249
21250 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21251
21252 TestCompletionCallback callback;
21253 auto trans =
21254 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21255
21256 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21257 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21258
21259 rv = callback.WaitForResult();
21260 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21261
21262 // Check that the Write didn't get called before ConfirmHandshake completed.
21263 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21264
21265 trans.reset();
21266
Matt Menke433de6d2020-03-04 00:24:1121267 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821268}
21269
David Benjamin2eb827f2019-04-29 18:31:0421270// Test the proxy and origin server each requesting both TLS client certificates
21271// and HTTP auth. This is a regression test for https://crbug.com/946406.
21272TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21273 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621274 session_deps_.proxy_resolution_service =
21275 ConfiguredProxyResolutionService::CreateFixed(
21276 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421277
21278 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21279 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21280
21281 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21282 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21283 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21284 ASSERT_TRUE(identity_proxy);
21285
21286 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21287 cert_request_info_origin->host_and_port =
21288 HostPortPair("www.example.org", 443);
21289
21290 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21291 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21292 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21293 ASSERT_TRUE(identity_origin);
21294
21295 HttpRequestInfo request;
21296 request.method = "GET";
21297 request.url = GURL("https://www.example.org/");
21298 request.traffic_annotation =
21299 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21300
David Benjamin7ebab032019-04-30 21:51:3021301 // First, the client connects to the proxy, which requests a client
21302 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421303 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21304 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21305 ssl_proxy1.expected_send_client_cert = false;
21306 StaticSocketDataProvider data1;
21307 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421309
David Benjamin7ebab032019-04-30 21:51:3021310 // The client responds with a certificate on a new connection. The handshake
21311 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421312 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21313 ssl_proxy2.expected_send_client_cert = true;
21314 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021315 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421316 std::vector<MockWrite> mock_writes2;
21317 std::vector<MockRead> mock_reads2;
21318 mock_writes2.emplace_back(
21319 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21320 "Host: www.example.org:443\r\n"
21321 "Proxy-Connection: keep-alive\r\n\r\n");
21322 mock_reads2.emplace_back(
21323 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21324 "Content-Length: 0\r\n"
21325 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021326 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421327 mock_writes2.emplace_back(
21328 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21329 "Host: www.example.org:443\r\n"
21330 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021331 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421332 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21333 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21334 // The origin requests client certificates.
21335 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21336 ssl_origin2.cert_request_info = cert_request_info_origin.get();
21337 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21338 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021339 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21340 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421341
David Benjamin7ebab032019-04-30 21:51:3021342 // The client responds to the origin client certificate request on a new
21343 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421344 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21345 ssl_proxy3.expected_send_client_cert = true;
21346 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21347 std::vector<MockWrite> mock_writes3;
21348 std::vector<MockRead> mock_reads3;
21349 mock_writes3.emplace_back(
21350 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21351 "Host: www.example.org:443\r\n"
21352 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021353 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421354 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21355 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21356 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21357 ssl_origin3.expected_send_client_cert = true;
21358 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021359 // The client sends the origin HTTP request, which results in another HTTP
21360 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421361 mock_writes3.emplace_back(
21362 "GET / HTTP/1.1\r\n"
21363 "Host: www.example.org\r\n"
21364 "Connection: keep-alive\r\n\r\n");
21365 mock_reads3.emplace_back(
21366 "HTTP/1.1 401 Unauthorized\r\n"
21367 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21368 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021369 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421370 mock_writes3.emplace_back(
21371 "GET / HTTP/1.1\r\n"
21372 "Host: www.example.org\r\n"
21373 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021374 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421375 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21376 mock_reads3.emplace_back(
21377 "HTTP/1.1 200 OK\r\n"
21378 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121379 // The client makes another request. This should reuse the socket with all
21380 // credentials cached.
21381 mock_writes3.emplace_back(
21382 "GET / HTTP/1.1\r\n"
21383 "Host: www.example.org\r\n"
21384 "Connection: keep-alive\r\n"
21385 // Authenticate as user:pass.
21386 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21387 mock_reads3.emplace_back(
21388 "HTTP/1.1 200 OK\r\n"
21389 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421390 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21391 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421394
21395 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21396
21397 // Start the request.
21398 TestCompletionCallback callback;
21399 auto trans =
21400 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21401 int rv = callback.GetResult(
21402 trans->Start(&request, callback.callback(), NetLogWithSource()));
21403
21404 // Handle the proxy client certificate challenge.
21405 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21406 SSLCertRequestInfo* cert_request_info =
21407 trans->GetResponseInfo()->cert_request_info.get();
21408 ASSERT_TRUE(cert_request_info);
21409 EXPECT_TRUE(cert_request_info->is_proxy);
21410 EXPECT_EQ(cert_request_info->host_and_port,
21411 cert_request_info_proxy->host_and_port);
21412 rv = callback.GetResult(trans->RestartWithCertificate(
21413 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21414 callback.callback()));
21415
21416 // Handle the proxy HTTP auth challenge.
21417 ASSERT_THAT(rv, IsOk());
21418 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21419 EXPECT_TRUE(
21420 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21421 rv = callback.GetResult(trans->RestartWithAuth(
21422 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21423 callback.callback()));
21424
21425 // Handle the origin client certificate challenge.
21426 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21427 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21428 ASSERT_TRUE(cert_request_info);
21429 EXPECT_FALSE(cert_request_info->is_proxy);
21430 EXPECT_EQ(cert_request_info->host_and_port,
21431 cert_request_info_origin->host_and_port);
21432 rv = callback.GetResult(trans->RestartWithCertificate(
21433 identity_origin->certificate(), identity_origin->ssl_private_key(),
21434 callback.callback()));
21435
21436 // Handle the origin HTTP auth challenge.
21437 ASSERT_THAT(rv, IsOk());
21438 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21439 EXPECT_TRUE(
21440 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21441 rv = callback.GetResult(trans->RestartWithAuth(
21442 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21443 callback.callback()));
21444
21445 // The request completes.
21446 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021447 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121448
21449 // Make a second request. This time all credentials are cached.
21450 trans =
21451 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21452 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21453 NetLogWithSource())),
21454 IsOk());
21455 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421456}
21457
21458// Test the proxy and origin server each requesting both TLS client certificates
21459// and HTTP auth and each HTTP auth closing the connection. This is a regression
21460// test for https://crbug.com/946406.
21461TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21462 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621463 session_deps_.proxy_resolution_service =
21464 ConfiguredProxyResolutionService::CreateFixed(
21465 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421466
21467 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21468 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21469
21470 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21471 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21472 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21473 ASSERT_TRUE(identity_proxy);
21474
21475 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21476 cert_request_info_origin->host_and_port =
21477 HostPortPair("www.example.org", 443);
21478
21479 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21480 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21481 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21482 ASSERT_TRUE(identity_origin);
21483
21484 HttpRequestInfo request;
21485 request.method = "GET";
21486 request.url = GURL("https://www.example.org/");
21487 request.traffic_annotation =
21488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21489
David Benjamin7ebab032019-04-30 21:51:3021490 // First, the client connects to the proxy, which requests a client
21491 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421492 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21493 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21494 ssl_proxy1.expected_send_client_cert = false;
21495 StaticSocketDataProvider data1;
21496 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021497 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421498
David Benjamin7ebab032019-04-30 21:51:3021499 // The client responds with a certificate on a new connection. The handshake
21500 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421501 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21502 ssl_proxy2.expected_send_client_cert = true;
21503 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021504 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421505 std::vector<MockWrite> mock_writes2;
21506 std::vector<MockRead> mock_reads2;
21507 mock_writes2.emplace_back(
21508 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21509 "Host: www.example.org:443\r\n"
21510 "Proxy-Connection: keep-alive\r\n\r\n");
21511 mock_reads2.emplace_back(
21512 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21513 "Content-Length: 0\r\n"
21514 "Proxy-Connection: close\r\n"
21515 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21516 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21517 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021518 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421519
David Benjamin7ebab032019-04-30 21:51:3021520 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421521 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21522 ssl_proxy3.expected_send_client_cert = true;
21523 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21524 std::vector<MockWrite> mock_writes3;
21525 std::vector<MockRead> mock_reads3;
21526 mock_writes3.emplace_back(
21527 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21528 "Host: www.example.org:443\r\n"
21529 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021530 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421531 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21532 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21533 // The origin requests client certificates.
21534 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21535 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21536 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21537 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021538 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21539 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421540
David Benjamin7ebab032019-04-30 21:51:3021541 // The client responds to the origin client certificate request on a new
21542 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421543 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21544 ssl_proxy4.expected_send_client_cert = true;
21545 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21546 std::vector<MockWrite> mock_writes4;
21547 std::vector<MockRead> mock_reads4;
21548 mock_writes4.emplace_back(
21549 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21550 "Host: www.example.org:443\r\n"
21551 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021552 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421553 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21554 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21555 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21556 ssl_origin4.expected_send_client_cert = true;
21557 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021558 // The client sends the origin HTTP request, which results in another HTTP
21559 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421560 mock_writes4.emplace_back(
21561 "GET / HTTP/1.1\r\n"
21562 "Host: www.example.org\r\n"
21563 "Connection: keep-alive\r\n\r\n");
21564 mock_reads4.emplace_back(
21565 "HTTP/1.1 401 Unauthorized\r\n"
21566 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21567 "Connection: close\r\n"
21568 "Content-Length: 0\r\n\r\n");
21569 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21570 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21572 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421573
David Benjamin7ebab032019-04-30 21:51:3021574 // The client retries with credentials on a new connection, and the request
21575 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421576 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21577 ssl_proxy5.expected_send_client_cert = true;
21578 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21579 std::vector<MockWrite> mock_writes5;
21580 std::vector<MockRead> mock_reads5;
21581 mock_writes5.emplace_back(
21582 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21583 "Host: www.example.org:443\r\n"
21584 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021585 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421586 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21587 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21588 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21589 ssl_origin5.expected_send_client_cert = true;
21590 ssl_origin5.expected_client_cert = identity_origin->certificate();
21591 mock_writes5.emplace_back(
21592 "GET / HTTP/1.1\r\n"
21593 "Host: www.example.org\r\n"
21594 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021595 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421596 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21597 mock_reads5.emplace_back(
21598 "HTTP/1.1 200 OK\r\n"
21599 "Connection: close\r\n"
21600 "Content-Length: 0\r\n\r\n");
21601 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21602 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021603 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421605
David Benjaminbac8dff2019-08-07 01:30:4121606 // The client makes a second request. This needs yet another connection, but
21607 // all credentials are cached.
21608 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21609 ssl_proxy6.expected_send_client_cert = true;
21610 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21611 std::vector<MockWrite> mock_writes6;
21612 std::vector<MockRead> mock_reads6;
21613 mock_writes6.emplace_back(
21614 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21615 "Host: www.example.org:443\r\n"
21616 "Proxy-Connection: keep-alive\r\n"
21617 // Authenticate as proxyuser:proxypass.
21618 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21619 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21620 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21621 ssl_origin6.expected_send_client_cert = true;
21622 ssl_origin6.expected_client_cert = identity_origin->certificate();
21623 mock_writes6.emplace_back(
21624 "GET / HTTP/1.1\r\n"
21625 "Host: www.example.org\r\n"
21626 "Connection: keep-alive\r\n"
21627 // Authenticate as user:pass.
21628 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21629 mock_reads6.emplace_back(
21630 "HTTP/1.1 200 OK\r\n"
21631 "Connection: close\r\n"
21632 "Content-Length: 0\r\n\r\n");
21633 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21634 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21635 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21637
David Benjamin2eb827f2019-04-29 18:31:0421638 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21639
21640 // Start the request.
21641 TestCompletionCallback callback;
21642 auto trans =
21643 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21644 int rv = callback.GetResult(
21645 trans->Start(&request, callback.callback(), NetLogWithSource()));
21646
21647 // Handle the proxy client certificate challenge.
21648 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21649 SSLCertRequestInfo* cert_request_info =
21650 trans->GetResponseInfo()->cert_request_info.get();
21651 ASSERT_TRUE(cert_request_info);
21652 EXPECT_TRUE(cert_request_info->is_proxy);
21653 EXPECT_EQ(cert_request_info->host_and_port,
21654 cert_request_info_proxy->host_and_port);
21655 rv = callback.GetResult(trans->RestartWithCertificate(
21656 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21657 callback.callback()));
21658
21659 // Handle the proxy HTTP auth challenge.
21660 ASSERT_THAT(rv, IsOk());
21661 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21662 EXPECT_TRUE(
21663 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21664 rv = callback.GetResult(trans->RestartWithAuth(
21665 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21666 callback.callback()));
21667
21668 // Handle the origin client certificate challenge.
21669 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21670 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21671 ASSERT_TRUE(cert_request_info);
21672 EXPECT_FALSE(cert_request_info->is_proxy);
21673 EXPECT_EQ(cert_request_info->host_and_port,
21674 cert_request_info_origin->host_and_port);
21675 rv = callback.GetResult(trans->RestartWithCertificate(
21676 identity_origin->certificate(), identity_origin->ssl_private_key(),
21677 callback.callback()));
21678
21679 // Handle the origin HTTP auth challenge.
21680 ASSERT_THAT(rv, IsOk());
21681 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21682 EXPECT_TRUE(
21683 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21684 rv = callback.GetResult(trans->RestartWithAuth(
21685 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21686 callback.callback()));
21687
21688 // The request completes.
21689 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021690 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121691
21692 // Make a second request. This time all credentials are cached.
21693 trans =
21694 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21695 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21696 NetLogWithSource())),
21697 IsOk());
21698 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021699}
21700
21701// Test the proxy requesting HTTP auth and the server requesting TLS client
21702// certificates. This is a regression test for https://crbug.com/946406.
21703TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21704 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621705 session_deps_.proxy_resolution_service =
21706 ConfiguredProxyResolutionService::CreateFixed(
21707 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin7ebab032019-04-30 21:51:3021708
21709 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21710 cert_request_info_origin->host_and_port =
21711 HostPortPair("www.example.org", 443);
21712
21713 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21714 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21715 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21716 ASSERT_TRUE(identity_origin);
21717
21718 HttpRequestInfo request;
21719 request.method = "GET";
21720 request.url = GURL("https://www.example.org/");
21721 request.traffic_annotation =
21722 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21723
21724 // The client connects to the proxy. The handshake succeeds.
21725 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21726 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21727 std::vector<MockWrite> mock_writes1;
21728 std::vector<MockRead> mock_reads1;
21729 mock_writes1.emplace_back(
21730 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21731 "Host: www.example.org:443\r\n"
21732 "Proxy-Connection: keep-alive\r\n\r\n");
21733 mock_reads1.emplace_back(
21734 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21735 "Content-Length: 0\r\n"
21736 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21737 // The client retries with credentials, and the request finally succeeds.
21738 mock_writes1.emplace_back(
21739 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21740 "Host: www.example.org:443\r\n"
21741 "Proxy-Connection: keep-alive\r\n"
21742 // Authenticate as proxyuser:proxypass.
21743 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21744 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21745 // The origin requests client certificates.
21746 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21747 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21748 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21749 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21750 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21751 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21752
21753 // The client responds to the origin client certificate request on a new
21754 // connection.
21755 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21756 std::vector<MockWrite> mock_writes2;
21757 std::vector<MockRead> mock_reads2;
21758 mock_writes2.emplace_back(
21759 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21760 "Host: www.example.org:443\r\n"
21761 "Proxy-Connection: keep-alive\r\n"
21762 // Authenticate as proxyuser:proxypass.
21763 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21764 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21765 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
21766 ssl_origin2.expected_send_client_cert = true;
21767 ssl_origin2.expected_client_cert = identity_origin->certificate();
21768 // The client sends the origin HTTP request, which succeeds.
21769 mock_writes2.emplace_back(
21770 "GET / HTTP/1.1\r\n"
21771 "Host: www.example.org\r\n"
21772 "Connection: keep-alive\r\n\r\n");
21773 mock_reads2.emplace_back(
21774 "HTTP/1.1 200 OK\r\n"
21775 "Content-Length: 0\r\n\r\n");
21776 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21777 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21778 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
21780
21781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21782
21783 // Start the request.
21784 TestCompletionCallback callback;
21785 auto trans =
21786 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21787 int rv = callback.GetResult(
21788 trans->Start(&request, callback.callback(), NetLogWithSource()));
21789
21790 // Handle the proxy HTTP auth challenge.
21791 ASSERT_THAT(rv, IsOk());
21792 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21793 EXPECT_TRUE(
21794 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21795 rv = callback.GetResult(trans->RestartWithAuth(
21796 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21797 callback.callback()));
21798
21799 // Handle the origin client certificate challenge.
21800 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21801 SSLCertRequestInfo* cert_request_info =
21802 trans->GetResponseInfo()->cert_request_info.get();
21803 ASSERT_TRUE(cert_request_info);
21804 EXPECT_FALSE(cert_request_info->is_proxy);
21805 EXPECT_EQ(cert_request_info->host_and_port,
21806 cert_request_info_origin->host_and_port);
21807 rv = callback.GetResult(trans->RestartWithCertificate(
21808 identity_origin->certificate(), identity_origin->ssl_private_key(),
21809 callback.callback()));
21810
21811 // The request completes.
21812 ASSERT_THAT(rv, IsOk());
21813 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421814}
21815
David Benjamin6e673a82019-04-30 22:52:5821816// Test that socket reuse works with client certificates.
21817TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
21818 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21819 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
21820
21821 std::unique_ptr<FakeClientCertIdentity> identity =
21822 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21823 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21824 ASSERT_TRUE(identity);
21825
21826 HttpRequestInfo request1;
21827 request1.method = "GET";
21828 request1.url = GURL("https://www.example.org/a");
21829 request1.traffic_annotation =
21830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21831
21832 HttpRequestInfo request2;
21833 request2.method = "GET";
21834 request2.url = GURL("https://www.example.org/b");
21835 request2.traffic_annotation =
21836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21837
21838 // The first connection results in a client certificate request.
21839 StaticSocketDataProvider data1;
21840 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21841 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21842 ssl1.cert_request_info = cert_request_info.get();
21843 ssl1.expected_send_client_cert = false;
21844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21845
21846 // The second connection succeeds and is usable for both requests.
21847 MockWrite mock_writes[] = {
21848 MockWrite("GET /a HTTP/1.1\r\n"
21849 "Host: www.example.org\r\n"
21850 "Connection: keep-alive\r\n\r\n"),
21851 MockWrite("GET /b HTTP/1.1\r\n"
21852 "Host: www.example.org\r\n"
21853 "Connection: keep-alive\r\n\r\n"),
21854 };
21855 MockRead mock_reads[] = {
21856 MockRead("HTTP/1.1 200 OK\r\n"
21857 "Content-Length: 0\r\n\r\n"),
21858 MockRead("HTTP/1.1 200 OK\r\n"
21859 "Content-Length: 0\r\n\r\n"),
21860 };
21861 StaticSocketDataProvider data2(mock_reads, mock_writes);
21862 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21863 SSLSocketDataProvider ssl2(ASYNC, OK);
21864 ssl2.expected_send_client_cert = true;
21865 ssl2.expected_client_cert = identity->certificate();
21866 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21867
21868 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21869
21870 // Start the first request. It succeeds after providing client certificates.
21871 TestCompletionCallback callback;
21872 auto trans =
21873 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21874 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
21875 NetLogWithSource())),
21876 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21877
21878 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
21879 ASSERT_TRUE(info);
21880 EXPECT_FALSE(info->is_proxy);
21881 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21882
21883 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21884 identity->certificate(), identity->ssl_private_key(),
21885 callback.callback())),
21886 IsOk());
21887 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21888
21889 // Make the second request. It completes without requesting client
21890 // certificates.
21891 trans =
21892 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21893 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21894 NetLogWithSource())),
21895 IsOk());
21896 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21897}
21898
Matt Menke166443c2019-05-24 18:45:5921899// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21900// sequence with two different NetworkIsolationKeys, the first and last have the
21901// same key, the second a different one. Checks that the requests are
21902// partitioned across sockets as expected.
21903TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721904 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21905 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21906 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21907 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921908
21909 for (bool partition_connections : {false, true}) {
21910 SCOPED_TRACE(partition_connections);
21911
21912 base::test::ScopedFeatureList feature_list;
21913 if (partition_connections) {
21914 feature_list.InitAndEnableFeature(
21915 features::kPartitionConnectionsByNetworkIsolationKey);
21916 } else {
21917 feature_list.InitAndDisableFeature(
21918 features::kPartitionConnectionsByNetworkIsolationKey);
21919 }
21920
21921 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21922
21923 // Reads and writes for the unpartitioned case, where only one socket is
21924 // used.
21925
21926 const MockWrite kUnpartitionedWrites[] = {
21927 MockWrite("GET /1 HTTP/1.1\r\n"
21928 "Host: foo.test\r\n"
21929 "Connection: keep-alive\r\n\r\n"),
21930 MockWrite("GET /2 HTTP/1.1\r\n"
21931 "Host: foo.test\r\n"
21932 "Connection: keep-alive\r\n\r\n"),
21933 MockWrite("GET /3 HTTP/1.1\r\n"
21934 "Host: foo.test\r\n"
21935 "Connection: keep-alive\r\n\r\n"),
21936 };
21937
21938 const MockRead kUnpartitionedReads[] = {
21939 MockRead("HTTP/1.1 200 OK\r\n"
21940 "Connection: keep-alive\r\n"
21941 "Content-Length: 1\r\n\r\n"
21942 "1"),
21943 MockRead("HTTP/1.1 200 OK\r\n"
21944 "Connection: keep-alive\r\n"
21945 "Content-Length: 1\r\n\r\n"
21946 "2"),
21947 MockRead("HTTP/1.1 200 OK\r\n"
21948 "Connection: keep-alive\r\n"
21949 "Content-Length: 1\r\n\r\n"
21950 "3"),
21951 };
21952
21953 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21954 kUnpartitionedWrites);
21955
21956 // Reads and writes for the partitioned case, where two sockets are used.
21957
21958 const MockWrite kPartitionedWrites1[] = {
21959 MockWrite("GET /1 HTTP/1.1\r\n"
21960 "Host: foo.test\r\n"
21961 "Connection: keep-alive\r\n\r\n"),
21962 MockWrite("GET /3 HTTP/1.1\r\n"
21963 "Host: foo.test\r\n"
21964 "Connection: keep-alive\r\n\r\n"),
21965 };
21966
21967 const MockRead kPartitionedReads1[] = {
21968 MockRead("HTTP/1.1 200 OK\r\n"
21969 "Connection: keep-alive\r\n"
21970 "Content-Length: 1\r\n\r\n"
21971 "1"),
21972 MockRead("HTTP/1.1 200 OK\r\n"
21973 "Connection: keep-alive\r\n"
21974 "Content-Length: 1\r\n\r\n"
21975 "3"),
21976 };
21977
21978 const MockWrite kPartitionedWrites2[] = {
21979 MockWrite("GET /2 HTTP/1.1\r\n"
21980 "Host: foo.test\r\n"
21981 "Connection: keep-alive\r\n\r\n"),
21982 };
21983
21984 const MockRead kPartitionedReads2[] = {
21985 MockRead("HTTP/1.1 200 OK\r\n"
21986 "Connection: keep-alive\r\n"
21987 "Content-Length: 1\r\n\r\n"
21988 "2"),
21989 };
21990
21991 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21992 kPartitionedWrites1);
21993 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21994 kPartitionedWrites2);
21995
21996 if (partition_connections) {
21997 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21998 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21999 } else {
22000 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
22001 }
22002
22003 TestCompletionCallback callback;
22004 HttpRequestInfo request1;
22005 request1.method = "GET";
22006 request1.url = GURL("http://foo.test/1");
22007 request1.traffic_annotation =
22008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22009 request1.network_isolation_key = network_isolation_key1;
22010 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22011 session.get());
22012 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22013 EXPECT_THAT(callback.GetResult(rv), IsOk());
22014 std::string response_data1;
22015 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22016 EXPECT_EQ("1", response_data1);
22017 trans1.reset();
22018
22019 HttpRequestInfo request2;
22020 request2.method = "GET";
22021 request2.url = GURL("http://foo.test/2");
22022 request2.traffic_annotation =
22023 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22024 request2.network_isolation_key = network_isolation_key2;
22025 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22026 session.get());
22027 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22028 EXPECT_THAT(callback.GetResult(rv), IsOk());
22029 std::string response_data2;
22030 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22031 EXPECT_EQ("2", response_data2);
22032 trans2.reset();
22033
22034 HttpRequestInfo request3;
22035 request3.method = "GET";
22036 request3.url = GURL("http://foo.test/3");
22037 request3.traffic_annotation =
22038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22039 request3.network_isolation_key = network_isolation_key1;
22040 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22041 session.get());
22042 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22043 EXPECT_THAT(callback.GetResult(rv), IsOk());
22044 std::string response_data3;
22045 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22046 EXPECT_EQ("3", response_data3);
22047 trans3.reset();
22048 }
22049}
22050
Matt Menkeae58eeb2019-05-24 21:09:5022051TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2722052 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22053 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22054 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
22055 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5022056
22057 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
22058 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
22059 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
22060 // the same way as the HTTP over H2 proxy case.
22061 for (bool use_proxy : {false, true}) {
22062 SCOPED_TRACE(use_proxy);
22063 if (use_proxy) {
22064 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622065 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkeae58eeb2019-05-24 21:09:5022066 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
22067 } else {
22068 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622069 ConfiguredProxyResolutionService::CreateDirect();
Matt Menkeae58eeb2019-05-24 21:09:5022070 }
22071 const char* url1 = nullptr;
22072 const char* url2 = nullptr;
22073 const char* url3 = nullptr;
22074 if (use_proxy) {
22075 url1 = "http://foo.test/1";
22076 url2 = "http://foo.test/2";
22077 url3 = "http://foo.test/3";
22078 } else {
22079 url1 = "https://foo.test/1";
22080 url2 = "https://foo.test/2";
22081 url3 = "https://foo.test/3";
22082 }
22083
22084 for (bool partition_connections : {false, true}) {
22085 SCOPED_TRACE(partition_connections);
22086
22087 base::test::ScopedFeatureList feature_list;
22088 if (partition_connections) {
22089 feature_list.InitAndEnableFeature(
22090 features::kPartitionConnectionsByNetworkIsolationKey);
22091 } else {
22092 feature_list.InitAndDisableFeature(
22093 features::kPartitionConnectionsByNetworkIsolationKey);
22094 }
22095
22096 std::unique_ptr<HttpNetworkSession> session(
22097 CreateSession(&session_deps_));
22098
22099 // Reads and writes for the unpartitioned case, where only one socket is
22100 // used.
22101
22102 SpdyTestUtil spdy_util;
22103 spdy::SpdySerializedFrame unpartitioned_req1(
22104 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
22105 spdy::SpdySerializedFrame unpartitioned_response1(
22106 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
22107 spdy::SpdySerializedFrame unpartitioned_body1(
22108 spdy_util.ConstructSpdyDataFrame(1, "1", true));
22109 spdy_util.UpdateWithStreamDestruction(1);
22110
22111 spdy::SpdySerializedFrame unpartitioned_req2(
22112 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
22113 spdy::SpdySerializedFrame unpartitioned_response2(
22114 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
22115 spdy::SpdySerializedFrame unpartitioned_body2(
22116 spdy_util.ConstructSpdyDataFrame(3, "2", true));
22117 spdy_util.UpdateWithStreamDestruction(3);
22118
22119 spdy::SpdySerializedFrame unpartitioned_req3(
22120 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
22121 spdy::SpdySerializedFrame unpartitioned_response3(
22122 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
22123 spdy::SpdySerializedFrame unpartitioned_body3(
22124 spdy_util.ConstructSpdyDataFrame(5, "3", true));
22125
22126 const MockWrite kUnpartitionedWrites[] = {
22127 CreateMockWrite(unpartitioned_req1, 0),
22128 CreateMockWrite(unpartitioned_req2, 3),
22129 CreateMockWrite(unpartitioned_req3, 6),
22130 };
22131
22132 const MockRead kUnpartitionedReads[] = {
22133 CreateMockRead(unpartitioned_response1, 1),
22134 CreateMockRead(unpartitioned_body1, 2),
22135 CreateMockRead(unpartitioned_response2, 4),
22136 CreateMockRead(unpartitioned_body2, 5),
22137 CreateMockRead(unpartitioned_response3, 7),
22138 CreateMockRead(unpartitioned_body3, 8),
22139 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
22140 };
22141
22142 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
22143 kUnpartitionedWrites);
22144
22145 // Reads and writes for the partitioned case, where two sockets are used.
22146
22147 SpdyTestUtil spdy_util2;
22148 spdy::SpdySerializedFrame partitioned_req1(
22149 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22150 spdy::SpdySerializedFrame partitioned_response1(
22151 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22152 spdy::SpdySerializedFrame partitioned_body1(
22153 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22154 spdy_util2.UpdateWithStreamDestruction(1);
22155
22156 spdy::SpdySerializedFrame partitioned_req3(
22157 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22158 spdy::SpdySerializedFrame partitioned_response3(
22159 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22160 spdy::SpdySerializedFrame partitioned_body3(
22161 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22162
22163 const MockWrite kPartitionedWrites1[] = {
22164 CreateMockWrite(partitioned_req1, 0),
22165 CreateMockWrite(partitioned_req3, 3),
22166 };
22167
22168 const MockRead kPartitionedReads1[] = {
22169 CreateMockRead(partitioned_response1, 1),
22170 CreateMockRead(partitioned_body1, 2),
22171 CreateMockRead(partitioned_response3, 4),
22172 CreateMockRead(partitioned_body3, 5),
22173 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22174 };
22175
22176 SpdyTestUtil spdy_util3;
22177 spdy::SpdySerializedFrame partitioned_req2(
22178 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22179 spdy::SpdySerializedFrame partitioned_response2(
22180 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22181 spdy::SpdySerializedFrame partitioned_body2(
22182 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22183
22184 const MockWrite kPartitionedWrites2[] = {
22185 CreateMockWrite(partitioned_req2, 0),
22186 };
22187
22188 const MockRead kPartitionedReads2[] = {
22189 CreateMockRead(partitioned_response2, 1),
22190 CreateMockRead(partitioned_body2, 2),
22191 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22192 };
22193
22194 SequencedSocketData partitioned_data1(kPartitionedReads1,
22195 kPartitionedWrites1);
22196 SequencedSocketData partitioned_data2(kPartitionedReads2,
22197 kPartitionedWrites2);
22198
22199 // No need to segment SSLDataProviders by whether or not partitioning is
22200 // enabled.
22201 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22202 ssl_data1.next_proto = kProtoHTTP2;
22203 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22204 ssl_data2.next_proto = kProtoHTTP2;
22205
22206 if (partition_connections) {
22207 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22209 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22211 } else {
22212 session_deps_.socket_factory->AddSocketDataProvider(
22213 &unpartitioned_data);
22214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22215 }
22216
22217 TestCompletionCallback callback;
22218 HttpRequestInfo request1;
22219 request1.method = "GET";
22220 request1.url = GURL(url1);
22221 request1.traffic_annotation =
22222 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22223 request1.network_isolation_key = network_isolation_key1;
22224 auto trans1 =
22225 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22226 int rv =
22227 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22228 EXPECT_THAT(callback.GetResult(rv), IsOk());
22229 std::string response_data1;
22230 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22231 EXPECT_EQ("1", response_data1);
22232 trans1.reset();
22233
22234 HttpRequestInfo request2;
22235 request2.method = "GET";
22236 request2.url = GURL(url2);
22237 request2.traffic_annotation =
22238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22239 request2.network_isolation_key = network_isolation_key2;
22240 auto trans2 =
22241 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22242 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22243 EXPECT_THAT(callback.GetResult(rv), IsOk());
22244 std::string response_data2;
22245 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22246 EXPECT_EQ("2", response_data2);
22247 trans2.reset();
22248
22249 HttpRequestInfo request3;
22250 request3.method = "GET";
22251 request3.url = GURL(url3);
22252 request3.traffic_annotation =
22253 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22254 request3.network_isolation_key = network_isolation_key1;
22255 auto trans3 =
22256 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22257 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22258 EXPECT_THAT(callback.GetResult(rv), IsOk());
22259 std::string response_data3;
22260 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22261 EXPECT_EQ("3", response_data3);
22262 trans3.reset();
22263 }
22264 }
22265}
22266
Matt Menke7281f872019-06-25 19:29:2522267// Preconnect two sockets with different NetworkIsolationKeys when
22268// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22269// request and make sure the correct socket is used. Loops three times,
22270// expecting to use the first preconnect, second preconnect, and neither.
22271TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22272 base::test::ScopedFeatureList feature_list;
22273 feature_list.InitAndEnableFeature(
22274 features::kPartitionConnectionsByNetworkIsolationKey);
22275
22276 enum class TestCase {
22277 kUseFirstPreconnect,
22278 kUseSecondPreconnect,
22279 kDontUsePreconnect,
22280 };
22281
Shivani Sharma8ae506c2019-07-21 21:08:2722282 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22283 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22284 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
22285 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
22286 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
22287 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2522288
22289 // Test that only preconnects with
22290 for (TestCase test_case :
22291 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22292 TestCase::kDontUsePreconnect}) {
22293 SpdySessionDependencies session_deps;
22294 // Make DNS lookups completely synchronously, so preconnects complete
22295 // immediately.
22296 session_deps.host_resolver->set_synchronous_mode(true);
22297
22298 const MockWrite kMockWrites[] = {
22299 MockWrite(ASYNC, 0,
22300 "GET / HTTP/1.1\r\n"
22301 "Host: www.foo.com\r\n"
22302 "Connection: keep-alive\r\n\r\n"),
22303 };
22304
22305 const MockRead kMockReads[] = {
22306 MockRead(ASYNC, 1,
22307 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22308 "hello"),
22309 };
22310
22311 // Used for the socket that will actually be used, which may or may not be
22312 // one of the preconnects
22313 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22314 kMockReads, kMockWrites);
22315
22316 // Used for the preconnects that won't actually be used.
22317 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22318 base::span<const MockRead>(),
22319 base::span<const MockWrite>());
22320 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22321 base::span<const MockRead>(),
22322 base::span<const MockWrite>());
22323
22324 NetworkIsolationKey network_isolation_key_for_request;
22325
22326 switch (test_case) {
22327 case TestCase::kUseFirstPreconnect:
22328 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22329 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22330 network_isolation_key_for_request = preconnect1_isolation_key;
22331 break;
22332 case TestCase::kUseSecondPreconnect:
22333 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22334 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22335 network_isolation_key_for_request = preconnect2_isolation_key;
22336 break;
22337 case TestCase::kDontUsePreconnect:
22338 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22339 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22340 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22341 network_isolation_key_for_request = not_preconnected_isolation_key;
22342 break;
22343 }
22344
22345 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22346
22347 // Preconnect sockets.
22348 HttpRequestInfo request;
22349 request.method = "GET";
22350 request.url = GURL("http://www.foo.com/");
22351 request.traffic_annotation =
22352 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22353
22354 request.network_isolation_key = preconnect1_isolation_key;
22355 session->http_stream_factory()->PreconnectStreams(1, request);
22356
22357 request.network_isolation_key = preconnect2_isolation_key;
22358 session->http_stream_factory()->PreconnectStreams(1, request);
22359
22360 request.network_isolation_key = network_isolation_key_for_request;
22361
22362 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22363
22364 // Make the request.
22365 TestCompletionCallback callback;
22366
22367 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22368
22369 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22371
22372 rv = callback.WaitForResult();
22373 EXPECT_THAT(rv, IsOk());
22374
22375 const HttpResponseInfo* response = trans.GetResponseInfo();
22376 ASSERT_TRUE(response);
22377 ASSERT_TRUE(response->headers);
22378 EXPECT_EQ(200, response->headers->response_code());
22379
22380 std::string response_data;
22381 rv = ReadTransaction(&trans, &response_data);
22382 EXPECT_THAT(rv, IsOk());
22383 EXPECT_EQ("hello", response_data);
22384
22385 if (test_case != TestCase::kDontUsePreconnect) {
22386 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22387 } else {
22388 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22389 }
22390 }
22391}
22392
David Benjamin6f2da652019-06-26 23:36:3522393// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22394// cache is isolated.
22395TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22396 base::test::ScopedFeatureList feature_list;
22397 feature_list.InitWithFeatures(
22398 {features::kPartitionConnectionsByNetworkIsolationKey,
22399 features::kPartitionSSLSessionsByNetworkIsolationKey},
22400 {});
22401
Shivani Sharma8ae506c2019-07-21 21:08:2722402 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22403 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22404 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22405 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522406 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22407
22408 // The server always sends Connection: close, so each request goes over a
22409 // distinct socket.
22410
22411 const MockWrite kWrites1[] = {
22412 MockWrite("GET /1 HTTP/1.1\r\n"
22413 "Host: foo.test\r\n"
22414 "Connection: keep-alive\r\n\r\n")};
22415
22416 const MockRead kReads1[] = {
22417 MockRead("HTTP/1.1 200 OK\r\n"
22418 "Connection: close\r\n"
22419 "Content-Length: 1\r\n\r\n"
22420 "1")};
22421
22422 const MockWrite kWrites2[] = {
22423 MockWrite("GET /2 HTTP/1.1\r\n"
22424 "Host: foo.test\r\n"
22425 "Connection: keep-alive\r\n\r\n")};
22426
22427 const MockRead kReads2[] = {
22428 MockRead("HTTP/1.1 200 OK\r\n"
22429 "Connection: close\r\n"
22430 "Content-Length: 1\r\n\r\n"
22431 "2")};
22432
22433 const MockWrite kWrites3[] = {
22434 MockWrite("GET /3 HTTP/1.1\r\n"
22435 "Host: foo.test\r\n"
22436 "Connection: keep-alive\r\n\r\n")};
22437
22438 const MockRead kReads3[] = {
22439 MockRead("HTTP/1.1 200 OK\r\n"
22440 "Connection: close\r\n"
22441 "Content-Length: 1\r\n\r\n"
22442 "3")};
22443
22444 StaticSocketDataProvider data1(kReads1, kWrites1);
22445 StaticSocketDataProvider data2(kReads2, kWrites2);
22446 StaticSocketDataProvider data3(kReads3, kWrites3);
22447 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22448 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22449 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22450
22451 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22452 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22453 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22454 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22455 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22456 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22457 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22458 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22459 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22462 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22463
22464 TestCompletionCallback callback;
22465 HttpRequestInfo request1;
22466 request1.method = "GET";
22467 request1.url = GURL("https://foo.test/1");
22468 request1.traffic_annotation =
22469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22470 request1.network_isolation_key = kNetworkIsolationKey1;
22471 auto trans1 =
22472 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22473 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22474 EXPECT_THAT(callback.GetResult(rv), IsOk());
22475 std::string response_data1;
22476 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22477 EXPECT_EQ("1", response_data1);
22478 trans1.reset();
22479
22480 HttpRequestInfo request2;
22481 request2.method = "GET";
22482 request2.url = GURL("https://foo.test/2");
22483 request2.traffic_annotation =
22484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22485 request2.network_isolation_key = kNetworkIsolationKey2;
22486 auto trans2 =
22487 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22488 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22489 EXPECT_THAT(callback.GetResult(rv), IsOk());
22490 std::string response_data2;
22491 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22492 EXPECT_EQ("2", response_data2);
22493 trans2.reset();
22494
22495 HttpRequestInfo request3;
22496 request3.method = "GET";
22497 request3.url = GURL("https://foo.test/3");
22498 request3.traffic_annotation =
22499 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22500 request3.network_isolation_key = kNetworkIsolationKey1;
22501 auto trans3 =
22502 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22503 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22504 EXPECT_THAT(callback.GetResult(rv), IsOk());
22505 std::string response_data3;
22506 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22507 EXPECT_EQ("3", response_data3);
22508 trans3.reset();
22509}
22510
22511// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22512// cache is isolated, for both origins and proxies.
22513TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22514 base::test::ScopedFeatureList feature_list;
22515 feature_list.InitWithFeatures(
22516 {features::kPartitionConnectionsByNetworkIsolationKey,
22517 features::kPartitionSSLSessionsByNetworkIsolationKey},
22518 {});
22519
Nicolas Arciniegad2013f92020-02-07 23:00:5622520 session_deps_.proxy_resolution_service =
22521 ConfiguredProxyResolutionService::CreateFixed(
22522 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin6f2da652019-06-26 23:36:3522523
Shivani Sharma8ae506c2019-07-21 21:08:2722524 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22525 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22526 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22527 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522528 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22529
22530 // Make both a tunneled and non-tunneled request.
22531 HttpRequestInfo request1;
22532 request1.method = "GET";
22533 request1.url = GURL("https://foo.test/1");
22534 request1.traffic_annotation =
22535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22536 request1.network_isolation_key = kNetworkIsolationKey1;
22537
22538 HttpRequestInfo request2;
22539 request2.method = "GET";
22540 request2.url = GURL("http://foo.test/2");
22541 request2.traffic_annotation =
22542 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22543 request2.network_isolation_key = kNetworkIsolationKey2;
22544
22545 const MockWrite kWrites1[] = {
22546 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22547 "Host: foo.test:443\r\n"
22548 "Proxy-Connection: keep-alive\r\n\r\n"),
22549 MockWrite("GET /1 HTTP/1.1\r\n"
22550 "Host: foo.test\r\n"
22551 "Connection: keep-alive\r\n\r\n")};
22552
22553 const MockRead kReads1[] = {
22554 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22555 MockRead("HTTP/1.1 200 OK\r\n"
22556 "Connection: close\r\n"
22557 "Content-Length: 1\r\n\r\n"
22558 "1")};
22559
22560 const MockWrite kWrites2[] = {
22561 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22562 "Host: foo.test\r\n"
22563 "Proxy-Connection: keep-alive\r\n\r\n")};
22564
22565 const MockRead kReads2[] = {
22566 MockRead("HTTP/1.1 200 OK\r\n"
22567 "Connection: close\r\n"
22568 "Content-Length: 1\r\n\r\n"
22569 "2")};
22570
22571 StaticSocketDataProvider data1(kReads1, kWrites1);
22572 StaticSocketDataProvider data2(kReads2, kWrites2);
22573 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22574 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22575 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22576
22577 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22578 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22579 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22580 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22581 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22582 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22583 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22584 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22585 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22587 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22588 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22589
22590 TestCompletionCallback callback;
22591 auto trans1 =
22592 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22593 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22594 EXPECT_THAT(callback.GetResult(rv), IsOk());
22595 std::string response_data1;
22596 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22597 EXPECT_EQ("1", response_data1);
22598 trans1.reset();
22599
22600 auto trans2 =
22601 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22602 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22603 EXPECT_THAT(callback.GetResult(rv), IsOk());
22604 std::string response_data2;
22605 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22606 EXPECT_EQ("2", response_data2);
22607 trans2.reset();
22608}
22609
David Benjaminef2f2a5a2019-07-16 19:21:3122610// Test that SSLConfig changes from SSLConfigService are picked up even when
22611// there are live sockets.
22612TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222613 SSLContextConfig ssl_context_config;
22614 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22615 auto ssl_config_service =
22616 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122617 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22618
22619 session_deps_.ssl_config_service = std::move(ssl_config_service);
22620
22621 // Make three requests. Between the second and third, the SSL config will
22622 // change.
22623 HttpRequestInfo request1;
22624 request1.method = "GET";
22625 request1.url = GURL("https://foo.test/1");
22626 request1.traffic_annotation =
22627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22628
22629 HttpRequestInfo request2;
22630 request2.method = "GET";
22631 request2.url = GURL("https://foo.test/2");
22632 request2.traffic_annotation =
22633 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22634
22635 HttpRequestInfo request3;
22636 request3.method = "GET";
22637 request3.url = GURL("https://foo.test/3");
22638 request3.traffic_annotation =
22639 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22640
22641 const MockWrite kWrites1[] = {
22642 MockWrite("GET /1 HTTP/1.1\r\n"
22643 "Host: foo.test\r\n"
22644 "Connection: keep-alive\r\n\r\n"),
22645 MockWrite("GET /2 HTTP/1.1\r\n"
22646 "Host: foo.test\r\n"
22647 "Connection: keep-alive\r\n\r\n"),
22648 };
22649
22650 const MockRead kReads1[] = {
22651 MockRead("HTTP/1.1 200 OK\r\n"
22652 "Connection: keep-alive\r\n"
22653 "Content-Length: 1\r\n\r\n"
22654 "1"),
22655 MockRead("HTTP/1.1 200 OK\r\n"
22656 "Connection: keep-alive\r\n"
22657 "Content-Length: 1\r\n\r\n"
22658 "2"),
22659 };
22660
22661 // The third request goes on a different socket because the SSL config has
22662 // changed.
22663 const MockWrite kWrites2[] = {
22664 MockWrite("GET /3 HTTP/1.1\r\n"
22665 "Host: foo.test\r\n"
22666 "Connection: keep-alive\r\n\r\n")};
22667
22668 const MockRead kReads2[] = {
22669 MockRead("HTTP/1.1 200 OK\r\n"
22670 "Connection: keep-alive\r\n"
22671 "Content-Length: 1\r\n\r\n"
22672 "3")};
22673
22674 StaticSocketDataProvider data1(kReads1, kWrites1);
22675 StaticSocketDataProvider data2(kReads2, kWrites2);
22676 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22677 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22678
22679 SSLSocketDataProvider ssl1(ASYNC, OK);
22680 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22681 SSLSocketDataProvider ssl2(ASYNC, OK);
22682 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22683 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22684 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22685
22686 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22687
22688 TestCompletionCallback callback;
22689 auto trans1 =
22690 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22691 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22692 EXPECT_THAT(callback.GetResult(rv), IsOk());
22693 std::string response_data1;
22694 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22695 EXPECT_EQ("1", response_data1);
22696 trans1.reset();
22697
22698 auto trans2 =
22699 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22700 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22701 EXPECT_THAT(callback.GetResult(rv), IsOk());
22702 std::string response_data2;
22703 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22704 EXPECT_EQ("2", response_data2);
22705 trans2.reset();
22706
David Benjamin151ec6b2019-08-02 19:38:5222707 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22708 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122709
22710 auto trans3 =
22711 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22712 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22713 EXPECT_THAT(callback.GetResult(rv), IsOk());
22714 std::string response_data3;
22715 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22716 EXPECT_EQ("3", response_data3);
22717 trans3.reset();
22718}
22719
22720TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222721 SSLContextConfig ssl_context_config;
22722 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22723 auto ssl_config_service =
22724 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122725 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22726
22727 session_deps_.ssl_config_service = std::move(ssl_config_service);
22728
22729 HttpRequestInfo request;
22730 request.method = "GET";
22731 request.url = GURL("https://foo.test/1");
22732 request.traffic_annotation =
22733 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22734
22735 // Make a socket which never connects.
22736 StaticSocketDataProvider data({}, {});
22737 session_deps_.socket_factory->AddSocketDataProvider(&data);
22738 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22739 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22741
22742 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22743
22744 TestCompletionCallback callback;
22745 auto trans =
22746 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22747 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22748 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22749
David Benjamin151ec6b2019-08-02 19:38:5222750 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22751 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122752
22753 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
22754}
22755
David Benjaminbac8dff2019-08-07 01:30:4122756// Test that HttpNetworkTransaction correctly handles existing sockets when the
22757// server requests a client certificate post-handshake (via a TLS
22758// renegotiation). This is a regression test for https://crbug.com/829184.
22759TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
22760 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
22761 TRAFFIC_ANNOTATION_FOR_TESTS);
22762
22763 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22764 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
22765
22766 std::unique_ptr<FakeClientCertIdentity> identity =
22767 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22768 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22769 ASSERT_TRUE(identity);
22770
22771 // This test will make several requests so that, when the client certificate
22772 // request comes in, we have a socket in use, an idle socket, and a socket for
22773 // an unrelated host.
22774 //
22775 // First, two long-lived requests which do not complete until after the client
22776 // certificate request. This arranges for sockets to be in use during the
22777 // request. They should not be interrupted.
22778 HttpRequestInfo request_long_lived;
22779 request_long_lived.method = "GET";
22780 request_long_lived.url = GURL("https://foo.test/long-lived");
22781 request_long_lived.traffic_annotation = kTrafficAnnotation;
22782
22783 HttpRequestInfo request_long_lived_bar;
22784 request_long_lived_bar.method = "GET";
22785 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
22786 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
22787
22788 // Next, make a request that needs client certificates.
22789 HttpRequestInfo request_auth;
22790 request_auth.method = "GET";
22791 request_auth.url = GURL("https://foo.test/auth");
22792 request_auth.traffic_annotation = kTrafficAnnotation;
22793
22794 // Before responding to the challenge, make a request to an unauthenticated
22795 // endpoint. This will result in an idle socket when the client certificate
22796 // challenge is resolved.
22797 HttpRequestInfo request_unauth;
22798 request_unauth.method = "GET";
22799 request_unauth.url = GURL("https://foo.test/unauth");
22800 request_unauth.traffic_annotation = kTrafficAnnotation;
22801
22802 // After all the preceding requests complete, end with two additional requests
22803 // to ensure pre-authentication foo.test sockets are not used and bar.test
22804 // sockets are unaffected.
22805 HttpRequestInfo request_post_auth;
22806 request_post_auth.method = "GET";
22807 request_post_auth.url = GURL("https://foo.test/post-auth");
22808 request_post_auth.traffic_annotation = kTrafficAnnotation;
22809
22810 HttpRequestInfo request_post_auth_bar;
22811 request_post_auth_bar.method = "GET";
22812 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
22813 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
22814
22815 // The sockets for /long-lived and /unauth complete their request but are
22816 // not allocated for /post-auth or /retry because SSL state has since changed.
22817 const MockWrite kLongLivedWrites[] = {
22818 MockWrite(ASYNC, 0,
22819 "GET /long-lived HTTP/1.1\r\n"
22820 "Host: foo.test\r\n"
22821 "Connection: keep-alive\r\n\r\n"),
22822 };
22823 const MockRead kLongLivedReads[] = {
22824 // Pause so /long-lived completes after the client presents client
22825 // certificates.
22826 MockRead(ASYNC, ERR_IO_PENDING, 1),
22827 MockRead(ASYNC, 2,
22828 "HTTP/1.1 200 OK\r\n"
22829 "Connection: keep-alive\r\n"
22830 "Content-Length: 10\r\n\r\n"
22831 "long-lived"),
22832 };
22833 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
22834 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
22835 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
22836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
22837
22838 // Requests for bar.test should be unaffected by foo.test and get allocated
22839 // a single socket.
22840 const MockWrite kBarWrites[] = {
22841 MockWrite(ASYNC, 0,
22842 "GET /long-lived HTTP/1.1\r\n"
22843 "Host: bar.test\r\n"
22844 "Connection: keep-alive\r\n\r\n"),
22845 MockWrite(ASYNC, 3,
22846 "GET /post-auth HTTP/1.1\r\n"
22847 "Host: bar.test\r\n"
22848 "Connection: keep-alive\r\n\r\n"),
22849 };
22850 const MockRead kBarReads[] = {
22851 // Pause on /long-lived so it completes after foo.test's authentication.
22852 MockRead(ASYNC, ERR_IO_PENDING, 1),
22853 MockRead(ASYNC, 2,
22854 "HTTP/1.1 200 OK\r\n"
22855 "Connection: keep-alive\r\n"
22856 "Content-Length: 10\r\n\r\n"
22857 "long-lived"),
22858 MockRead(ASYNC, 4,
22859 "HTTP/1.1 200 OK\r\n"
22860 "Connection: keep-alive\r\n"
22861 "Content-Length: 9\r\n\r\n"
22862 "post-auth"),
22863 };
22864 SequencedSocketData data_bar(kBarReads, kBarWrites);
22865 SSLSocketDataProvider ssl_bar(ASYNC, OK);
22866 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
22867 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
22868
22869 // Requesting /auth results in a post-handshake client certificate challenge.
22870 const MockWrite kAuthWrites[] = {
22871 MockWrite(ASYNC, 0,
22872 "GET /auth HTTP/1.1\r\n"
22873 "Host: foo.test\r\n"
22874 "Connection: keep-alive\r\n\r\n"),
22875 };
22876 const MockRead kAuthReads[] = {
22877 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
22878 };
22879 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
22880 SSLSocketDataProvider ssl_auth(ASYNC, OK);
22881 ssl_auth.cert_request_info = cert_request_info.get();
22882 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22884
22885 // Requesting /unauth completes.
22886 const MockWrite kUnauthWrites[] = {
22887 MockWrite(ASYNC, 0,
22888 "GET /unauth HTTP/1.1\r\n"
22889 "Host: foo.test\r\n"
22890 "Connection: keep-alive\r\n\r\n"),
22891 };
22892 const MockRead kUnauthReads[] = {
22893 MockRead(ASYNC, 1,
22894 "HTTP/1.1 200 OK\r\n"
22895 "Connection: keep-alive\r\n"
22896 "Content-Length: 6\r\n\r\n"
22897 "unauth"),
22898 };
22899 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22900 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22901 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22902 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22903
22904 // When the client certificate is selected, /auth is retried on a new
22905 // connection. In particular, it should not be retried on |data_unauth|,
22906 // which would not honor the new client certificate configuration.
22907 const MockWrite kRetryWrites[] = {
22908 MockWrite(ASYNC, 0,
22909 "GET /auth HTTP/1.1\r\n"
22910 "Host: foo.test\r\n"
22911 "Connection: keep-alive\r\n\r\n"),
22912 };
22913 const MockRead kRetryReads[] = {
22914 MockRead(ASYNC, 1,
22915 "HTTP/1.1 200 OK\r\n"
22916 // Close the connection so we test that /post-auth is not
22917 // allocated to |data_unauth| or |data_long_lived|.
22918 "Connection: close\r\n"
22919 "Content-Length: 4\r\n\r\n"
22920 "auth"),
22921 };
22922 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22923 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22924 ssl_retry.expected_send_client_cert = true;
22925 ssl_retry.expected_client_cert = identity->certificate();
22926 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22928
22929 // /post-auth gets its own socket.
22930 const MockWrite kPostAuthWrites[] = {
22931 MockWrite(ASYNC, 0,
22932 "GET /post-auth HTTP/1.1\r\n"
22933 "Host: foo.test\r\n"
22934 "Connection: keep-alive\r\n\r\n"),
22935 };
22936 const MockRead kPostAuthReads[] = {
22937 MockRead(ASYNC, 1,
22938 "HTTP/1.1 200 OK\r\n"
22939 "Connection: keep-alive\r\n"
22940 "Content-Length: 9\r\n\r\n"
22941 "post-auth"),
22942 };
22943 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22944 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22945 ssl_post_auth.expected_send_client_cert = true;
22946 ssl_post_auth.expected_client_cert = identity->certificate();
22947 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22949
22950 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22951
22952 // Start the two long-lived requests.
22953 TestCompletionCallback callback_long_lived;
22954 auto trans_long_lived =
22955 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22956 int rv = trans_long_lived->Start(
22957 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22958 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22959 data_long_lived.RunUntilPaused();
22960
22961 TestCompletionCallback callback_long_lived_bar;
22962 auto trans_long_lived_bar =
22963 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22964 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22965 callback_long_lived_bar.callback(),
22966 NetLogWithSource());
22967 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22968 data_bar.RunUntilPaused();
22969
22970 // Request /auth. This gives a client certificate challenge.
22971 TestCompletionCallback callback_auth;
22972 auto trans_auth =
22973 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22974 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22975 NetLogWithSource());
22976 EXPECT_THAT(callback_auth.GetResult(rv),
22977 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22978
22979 // Make an unauthenticated request. This completes.
22980 TestCompletionCallback callback_unauth;
22981 auto trans_unauth =
22982 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22983 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22984 NetLogWithSource());
22985 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22986 std::string response_unauth;
22987 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22988 EXPECT_EQ("unauth", response_unauth);
22989 trans_unauth.reset();
22990
22991 // Complete the authenticated request.
22992 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22993 identity->ssl_private_key(),
22994 callback_auth.callback());
22995 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22996 std::string response_auth;
22997 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22998 EXPECT_EQ("auth", response_auth);
22999 trans_auth.reset();
23000
23001 // Complete the long-lived requests.
23002 data_long_lived.Resume();
23003 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
23004 std::string response_long_lived;
23005 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
23006 IsOk());
23007 EXPECT_EQ("long-lived", response_long_lived);
23008 trans_long_lived.reset();
23009
23010 data_bar.Resume();
23011 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
23012 std::string response_long_lived_bar;
23013 EXPECT_THAT(
23014 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
23015 IsOk());
23016 EXPECT_EQ("long-lived", response_long_lived_bar);
23017 trans_long_lived_bar.reset();
23018
23019 // Run the post-authentication requests.
23020 TestCompletionCallback callback_post_auth;
23021 auto trans_post_auth =
23022 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23023 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
23024 NetLogWithSource());
23025 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
23026 std::string response_post_auth;
23027 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
23028 IsOk());
23029 EXPECT_EQ("post-auth", response_post_auth);
23030 trans_post_auth.reset();
23031
23032 TestCompletionCallback callback_post_auth_bar;
23033 auto trans_post_auth_bar =
23034 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23035 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
23036 callback_post_auth_bar.callback(),
23037 NetLogWithSource());
23038 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
23039 std::string response_post_auth_bar;
23040 EXPECT_THAT(
23041 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
23042 IsOk());
23043 EXPECT_EQ("post-auth", response_post_auth_bar);
23044 trans_post_auth_bar.reset();
23045}
23046
[email protected]89ceba9a2009-03-21 03:46:0623047} // namespace net