blob: 957a6b0d0e871f7c5248f2bc1611f464e663f945 [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
[email protected]15a5ccf82008-10-23 19:57:43579// Fill |str| with a long header list that consumes >= |size| bytes.
580void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51581 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19582 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
583 const int sizeof_row = strlen(row);
584 const int num_rows = static_cast<int>(
585 ceil(static_cast<float>(size) / sizeof_row));
586 const int sizeof_data = num_rows * sizeof_row;
587 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43588 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51589
[email protected]4ddaf2502008-10-23 18:26:19590 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43591 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19592}
593
thakis84dff942015-07-28 20:47:38594#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09595uint64_t MockGetMSTime() {
596 // Tue, 23 May 2017 20:13:07 +0000
597 return 131400439870000000;
598}
599
[email protected]385a4672009-03-11 22:21:29600// Alternative functions that eliminate randomness and dependency on the local
601// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37602void MockGenerateRandom(uint8_t* output, size_t n) {
603 // This is set to 0xaa because the client challenge for testing in
604 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
605 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29606}
607
[email protected]fe2bc6a2009-03-23 16:52:20608std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37609 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29610}
thakis84dff942015-07-28 20:47:38611#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29612
Matt Menked6fd2a52019-03-20 06:14:36613class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31614 public:
Matt Menked6fd2a52019-03-20 06:14:36615 explicit CaptureGroupIdTransportSocketPool(
616 const CommonConnectJobParams* common_connect_job_params)
617 : TransportClientSocketPool(0,
618 0,
619 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36620 ProxyServer::Direct(),
621 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52622 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18623
Matt Menkef6edce752019-03-19 17:21:56624 const ClientSocketPool::GroupId& last_group_id_received() const {
625 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49626 }
627
Tarun Bansal162eabe52018-01-20 01:16:39628 bool socket_requested() const { return socket_requested_; }
629
Matt Menke28ac03e2019-02-25 22:25:50630 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56631 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03632 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28633 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50634 RequestPriority priority,
635 const SocketTag& socket_tag,
636 ClientSocketPool::RespectLimits respect_limits,
637 ClientSocketHandle* handle,
638 CompletionOnceCallback callback,
639 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
640 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56641 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39642 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31643 return ERR_IO_PENDING;
644 }
Matt Menkef6edce752019-03-19 17:21:56645 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21646 ClientSocketHandle* handle,
647 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56648 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09649 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24650 int64_t generation) override {}
Matt Menke433de6d2020-03-04 00:24:11651 void CloseIdleSockets(const char* net_log_reason_utf8) override {}
652 void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
653 const char* net_log_reason_utf8) override {}
dmichaeld6e570d2014-12-18 22:30:57654 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56655 size_t IdleSocketCountInGroup(
656 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31657 return 0;
658 }
Matt Menkef6edce752019-03-19 17:21:56659 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57660 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31661 return LOAD_STATE_IDLE;
662 }
[email protected]d80a4322009-08-14 07:07:49663
664 private:
Matt Menkef6edce752019-03-19 17:21:56665 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39666 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31667};
668
[email protected]231d5a32008-09-13 00:45:27669//-----------------------------------------------------------------------------
670
[email protected]79cb5c12011-09-12 13:12:04671// Helper functions for validating that AuthChallengeInfo's are correctly
672// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58673bool CheckBasicServerAuth(
674 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04675 if (!auth_challenge)
676 return false;
677 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43678 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04679 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19680 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04681 return true;
682}
683
David Benjamin2eb827f2019-04-29 18:31:04684bool CheckBasicSecureServerAuth(
685 const base::Optional<AuthChallengeInfo>& auth_challenge) {
686 if (!auth_challenge)
687 return false;
688 EXPECT_FALSE(auth_challenge->is_proxy);
689 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
690 EXPECT_EQ("MyRealm1", auth_challenge->realm);
691 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
692 return true;
693}
694
Emily Starkf2c9bbd2019-04-09 17:08:58695bool CheckBasicProxyAuth(
696 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04697 if (!auth_challenge)
698 return false;
699 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43700 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
701 EXPECT_EQ("MyRealm1", auth_challenge->realm);
702 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
703 return true;
704}
705
Emily Starkf2c9bbd2019-04-09 17:08:58706bool CheckBasicSecureProxyAuth(
707 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43708 if (!auth_challenge)
709 return false;
710 EXPECT_TRUE(auth_challenge->is_proxy);
711 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04712 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19713 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04714 return true;
715}
716
Emily Starkf2c9bbd2019-04-09 17:08:58717bool CheckDigestServerAuth(
718 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04719 if (!auth_challenge)
720 return false;
721 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43722 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04723 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19724 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04725 return true;
726}
727
thakis84dff942015-07-28 20:47:38728#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58729bool CheckNTLMServerAuth(
730 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04731 if (!auth_challenge)
732 return false;
733 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55734 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04735 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19736 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04737 return true;
738}
David Benjamin5cb91132018-04-06 05:54:49739
Emily Starkf2c9bbd2019-04-09 17:08:58740bool CheckNTLMProxyAuth(
741 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49742 if (!auth_challenge)
743 return false;
744 EXPECT_TRUE(auth_challenge->is_proxy);
745 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
746 EXPECT_EQ(std::string(), auth_challenge->realm);
747 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
748 return true;
749}
thakis84dff942015-07-28 20:47:38750#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04751
[email protected]448d4ca52012-03-04 04:12:23752} // namespace
753
Shivani Sharma8ae506c2019-07-21 21:08:27754// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
755// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
756
bncd16676a2016-07-20 16:23:01757TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09758 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16759 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27760}
761
bncd16676a2016-07-20 16:23:01762TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27763 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35764 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
765 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06766 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27767 };
Ryan Sleevib8d7ea02018-05-07 20:01:01768 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01769 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27770 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
771 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01772 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22773 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47774 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59775
776 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27777}
778
779// Response with no status line.
bncd16676a2016-07-20 16:23:01780TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27781 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35782 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06783 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27784 };
Ryan Sleevib8d7ea02018-05-07 20:01:01785 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41786 EXPECT_THAT(out.rv, IsOk());
787 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
788 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01789 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41790 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27791}
792
mmenkea7da6da2016-09-01 21:56:52793// Response with no status line, and a weird port. Should fail by default.
794TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
795 MockRead data_reads[] = {
796 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
797 };
798
Ryan Sleevib8d7ea02018-05-07 20:01:01799 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52800 session_deps_.socket_factory->AddSocketDataProvider(&data);
801
802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
803
krasinc06a72a2016-12-21 03:42:46804 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58805 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19806 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52807
mmenkea7da6da2016-09-01 21:56:52808 request.method = "GET";
809 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e2018-02-07 07:41:10810 request.traffic_annotation =
811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
812
mmenkea7da6da2016-09-01 21:56:52813 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20814 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52815 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
816}
817
Shivani Sharmafdcaefd2017-11-02 00:12:26818// Tests that request info can be destroyed after the headers phase is complete.
819TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
820 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
821 auto trans =
822 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
823
824 MockRead data_reads[] = {
825 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
826 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
827 };
Ryan Sleevib8d7ea02018-05-07 20:01:01828 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26829 session_deps_.socket_factory->AddSocketDataProvider(&data);
830
831 TestCompletionCallback callback;
832
833 {
834 auto request = std::make_unique<HttpRequestInfo>();
835 request->method = "GET";
836 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10837 request->traffic_annotation =
838 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26839
840 int rv =
841 trans->Start(request.get(), callback.callback(), NetLogWithSource());
842
843 EXPECT_THAT(callback.GetResult(rv), IsOk());
844 } // Let request info be destroyed.
845
846 trans.reset();
847}
848
dalyk6d7a8c52019-12-18 21:43:01849// Test that a failure in resolving the hostname is retrievable.
850TEST_F(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
851 HttpRequestInfo request;
852 request.method = "GET";
853 request.url = GURL("http://www.example.org/");
854 request.traffic_annotation =
855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
856
857 RecordingTestNetLog log;
858 MockHostResolver* resolver = new MockHostResolver();
859 resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
860 session_deps_.net_log = &log;
861 session_deps_.host_resolver.reset(resolver);
862 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
863 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
864 TestCompletionCallback callback;
865
866 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
867 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
868 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
869
870 const HttpResponseInfo* response = trans.GetResponseInfo();
871 ASSERT_TRUE(response);
872 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
873}
874
[email protected]231d5a32008-09-13 00:45:27875// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01876TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27877 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35878 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06879 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27880 };
Ryan Sleevib8d7ea02018-05-07 20:01:01881 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01882 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27883 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
884 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01885 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22886 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27887}
888
889// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01890TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27891 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35892 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06893 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27894 };
Ryan Sleevib8d7ea02018-05-07 20:01:01895 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01896 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27897 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
898 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01899 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22900 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27901}
902
903// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01904TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27905 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35906 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06907 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27908 };
Ryan Sleevib8d7ea02018-05-07 20:01:01909 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41910 EXPECT_THAT(out.rv, IsOk());
911 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
912 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01913 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41914 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27915}
916
917// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01918TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27919 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35920 MockRead("\n"),
921 MockRead("\n"),
922 MockRead("Q"),
923 MockRead("J"),
924 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06925 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27926 };
Ryan Sleevib8d7ea02018-05-07 20:01:01927 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01928 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27929 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
930 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01931 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22932 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27933}
934
935// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01936TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27937 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35938 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06939 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27940 };
Ryan Sleevib8d7ea02018-05-07 20:01:01941 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41942 EXPECT_THAT(out.rv, IsOk());
943 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
944 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01945 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41946 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52947}
948
[email protected]f9d44aa2008-09-23 23:57:17949// Simulate a 204 response, lacking a Content-Length header, sent over a
950// persistent connection. The response should still terminate since a 204
951// cannot have a response body.
bncd16676a2016-07-20 16:23:01952TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19953 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17954 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35955 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19956 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06957 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17958 };
Ryan Sleevib8d7ea02018-05-07 20:01:01959 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01960 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17961 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
962 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01963 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22964 int64_t response_size = reads_size - strlen(junk);
965 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17966}
967
[email protected]0877e3d2009-10-17 22:29:57968// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01969TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19970 std::string final_chunk = "0\r\n\r\n";
971 std::string extra_data = "HTTP/1.1 200 OK\r\n";
972 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57973 MockRead data_reads[] = {
974 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
975 MockRead("5\r\nHello\r\n"),
976 MockRead("1\r\n"),
977 MockRead(" \r\n"),
978 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19979 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06980 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57981 };
Ryan Sleevib8d7ea02018-05-07 20:01:01982 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01983 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57984 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
985 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01986 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22987 int64_t response_size = reads_size - extra_data.size();
988 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57989}
990
[email protected]9fe44f52010-09-23 18:36:00991// Next tests deal with http://crbug.com/56344.
992
bncd16676a2016-07-20 16:23:01993TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00994 MultipleContentLengthHeadersNoTransferEncoding) {
995 MockRead data_reads[] = {
996 MockRead("HTTP/1.1 200 OK\r\n"),
997 MockRead("Content-Length: 10\r\n"),
998 MockRead("Content-Length: 5\r\n\r\n"),
999 };
Ryan Sleevib8d7ea02018-05-07 20:01:011000 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011001 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001002}
1003
bncd16676a2016-07-20 16:23:011004TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041005 DuplicateContentLengthHeadersNoTransferEncoding) {
1006 MockRead data_reads[] = {
1007 MockRead("HTTP/1.1 200 OK\r\n"),
1008 MockRead("Content-Length: 5\r\n"),
1009 MockRead("Content-Length: 5\r\n\r\n"),
1010 MockRead("Hello"),
1011 };
Ryan Sleevib8d7ea02018-05-07 20:01:011012 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011013 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041014 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1015 EXPECT_EQ("Hello", out.response_data);
1016}
1017
bncd16676a2016-07-20 16:23:011018TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041019 ComplexContentLengthHeadersNoTransferEncoding) {
1020 // More than 2 dupes.
1021 {
1022 MockRead data_reads[] = {
1023 MockRead("HTTP/1.1 200 OK\r\n"),
1024 MockRead("Content-Length: 5\r\n"),
1025 MockRead("Content-Length: 5\r\n"),
1026 MockRead("Content-Length: 5\r\n\r\n"),
1027 MockRead("Hello"),
1028 };
Ryan Sleevib8d7ea02018-05-07 20:01:011029 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011030 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041031 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1032 EXPECT_EQ("Hello", out.response_data);
1033 }
1034 // HTTP/1.0
1035 {
1036 MockRead data_reads[] = {
1037 MockRead("HTTP/1.0 200 OK\r\n"),
1038 MockRead("Content-Length: 5\r\n"),
1039 MockRead("Content-Length: 5\r\n"),
1040 MockRead("Content-Length: 5\r\n\r\n"),
1041 MockRead("Hello"),
1042 };
Ryan Sleevib8d7ea02018-05-07 20:01:011043 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011044 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041045 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1046 EXPECT_EQ("Hello", out.response_data);
1047 }
1048 // 2 dupes and one mismatched.
1049 {
1050 MockRead data_reads[] = {
1051 MockRead("HTTP/1.1 200 OK\r\n"),
1052 MockRead("Content-Length: 10\r\n"),
1053 MockRead("Content-Length: 10\r\n"),
1054 MockRead("Content-Length: 5\r\n\r\n"),
1055 };
Ryan Sleevib8d7ea02018-05-07 20:01:011056 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011057 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041058 }
1059}
1060
bncd16676a2016-07-20 16:23:011061TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001062 MultipleContentLengthHeadersTransferEncoding) {
1063 MockRead data_reads[] = {
1064 MockRead("HTTP/1.1 200 OK\r\n"),
1065 MockRead("Content-Length: 666\r\n"),
1066 MockRead("Content-Length: 1337\r\n"),
1067 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1068 MockRead("5\r\nHello\r\n"),
1069 MockRead("1\r\n"),
1070 MockRead(" \r\n"),
1071 MockRead("5\r\nworld\r\n"),
1072 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061073 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001074 };
Ryan Sleevib8d7ea02018-05-07 20:01:011075 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011076 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001077 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1078 EXPECT_EQ("Hello world", out.response_data);
1079}
1080
[email protected]1628fe92011-10-04 23:04:551081// Next tests deal with http://crbug.com/98895.
1082
1083// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011084TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551085 MockRead data_reads[] = {
1086 MockRead("HTTP/1.1 200 OK\r\n"),
1087 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1088 MockRead("Content-Length: 5\r\n\r\n"),
1089 MockRead("Hello"),
1090 };
Ryan Sleevib8d7ea02018-05-07 20:01:011091 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011092 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551093 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1094 EXPECT_EQ("Hello", out.response_data);
1095}
1096
[email protected]54a9c6e52012-03-21 20:10:591097// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011098TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551099 MockRead data_reads[] = {
1100 MockRead("HTTP/1.1 200 OK\r\n"),
1101 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1102 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1103 MockRead("Content-Length: 5\r\n\r\n"),
1104 MockRead("Hello"),
1105 };
Ryan Sleevib8d7ea02018-05-07 20:01:011106 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011107 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591108 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1109 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551110}
1111
1112// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011113TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551114 MockRead data_reads[] = {
1115 MockRead("HTTP/1.1 200 OK\r\n"),
1116 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1117 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1118 MockRead("Content-Length: 5\r\n\r\n"),
1119 MockRead("Hello"),
1120 };
Ryan Sleevib8d7ea02018-05-07 20:01:011121 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011122 EXPECT_THAT(out.rv,
1123 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551124}
1125
[email protected]54a9c6e52012-03-21 20:10:591126// Checks that two identical Location headers result in no error.
1127// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011128TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551129 MockRead data_reads[] = {
1130 MockRead("HTTP/1.1 302 Redirect\r\n"),
1131 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591132 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551133 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061134 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551135 };
1136
1137 HttpRequestInfo request;
1138 request.method = "GET";
1139 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101140 request.traffic_annotation =
1141 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551142
danakj1fd259a02016-04-16 03:17:091143 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161144 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551145
Ryan Sleevib8d7ea02018-05-07 20:01:011146 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071147 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551148
[email protected]49639fa2011-12-20 23:22:411149 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551150
tfarina42834112016-09-22 13:38:201151 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011152 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551153
robpercival214763f2016-07-01 23:27:011154 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551155
bnc691fda62016-08-12 00:43:161156 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521157 ASSERT_TRUE(response);
1158 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551159 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1160 std::string url;
1161 EXPECT_TRUE(response->headers->IsRedirect(&url));
1162 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471163 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551164}
1165
[email protected]1628fe92011-10-04 23:04:551166// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011167TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551168 MockRead data_reads[] = {
1169 MockRead("HTTP/1.1 302 Redirect\r\n"),
1170 MockRead("Location: http://good.com/\r\n"),
1171 MockRead("Location: http://evil.com/\r\n"),
1172 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061173 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551174 };
Ryan Sleevib8d7ea02018-05-07 20:01:011175 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011176 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551177}
1178
[email protected]ef0faf2e72009-03-05 23:27:231179// Do a request using the HEAD method. Verify that we don't try to read the
1180// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011181TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421182 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231183 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231184 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101185 request.traffic_annotation =
1186 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231187
danakj1fd259a02016-04-16 03:17:091188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161189 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271190
[email protected]ef0faf2e72009-03-05 23:27:231191 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131192 MockWrite("HEAD / HTTP/1.1\r\n"
1193 "Host: www.example.org\r\n"
1194 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231195 };
1196 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231197 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1198 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231199
mmenked39192ee2015-12-09 00:57:231200 // No response body because the test stops reading here.
1201 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231202 };
1203
Ryan Sleevib8d7ea02018-05-07 20:01:011204 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071205 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231206
[email protected]49639fa2011-12-20 23:22:411207 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231208
tfarina42834112016-09-22 13:38:201209 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231211
1212 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231214
bnc691fda62016-08-12 00:43:161215 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521216 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231217
1218 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521219 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231220 EXPECT_EQ(1234, response->headers->GetContentLength());
1221 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471222 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]ef0faf2e72009-03-05 23:27:231223
1224 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101225 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231226 bool has_server_header = response->headers->EnumerateHeader(
1227 &iter, "Server", &server_header);
1228 EXPECT_TRUE(has_server_header);
1229 EXPECT_EQ("Blah", server_header);
1230
1231 // Reading should give EOF right away, since there is no message body
1232 // (despite non-zero content-length).
1233 std::string response_data;
bnc691fda62016-08-12 00:43:161234 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011235 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231236 EXPECT_EQ("", response_data);
1237}
1238
bncd16676a2016-07-20 16:23:011239TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091240 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521241
1242 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351243 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1244 MockRead("hello"),
1245 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1246 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061247 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521248 };
Ryan Sleevib8d7ea02018-05-07 20:01:011249 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071250 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521251
[email protected]0b0bf032010-09-21 18:08:501252 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521253 "hello", "world"
1254 };
1255
1256 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421257 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521258 request.method = "GET";
bncce36dca22015-04-21 22:11:231259 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101260 request.traffic_annotation =
1261 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521262
bnc691fda62016-08-12 00:43:161263 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271264
[email protected]49639fa2011-12-20 23:22:411265 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521266
tfarina42834112016-09-22 13:38:201267 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011268 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521269
1270 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011271 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521272
bnc691fda62016-08-12 00:43:161273 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521274 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521275
wezca1070932016-05-26 20:30:521276 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251277 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471278 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521279
1280 std::string response_data;
bnc691fda62016-08-12 00:43:161281 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011282 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251283 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521284 }
1285}
1286
bncd16676a2016-07-20 16:23:011287TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091288 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221289 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191290 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221291 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271292
[email protected]1c773ea12009-04-28 19:58:421293 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521294 request.method = "POST";
1295 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271296 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:101297 request.traffic_annotation =
1298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521299
shivanishab9a143952016-09-19 17:23:411300 // Check the upload progress returned before initialization is correct.
1301 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1302 EXPECT_EQ(0u, progress.size());
1303 EXPECT_EQ(0u, progress.position());
1304
danakj1fd259a02016-04-16 03:17:091305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161306 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271307
initial.commit586acc5fe2008-07-26 22:42:521308 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351309 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1310 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1311 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061312 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521313 };
Ryan Sleevib8d7ea02018-05-07 20:01:011314 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071315 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521316
[email protected]49639fa2011-12-20 23:22:411317 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521318
tfarina42834112016-09-22 13:38:201319 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011320 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521321
1322 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011323 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521324
bnc691fda62016-08-12 00:43:161325 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521326 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521327
wezca1070932016-05-26 20:30:521328 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251329 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521330
1331 std::string response_data;
bnc691fda62016-08-12 00:43:161332 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011333 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251334 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521335}
1336
[email protected]3a2d3662009-03-27 03:49:141337// This test is almost the same as Ignores100 above, but the response contains
1338// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571339// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011340TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421341 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141342 request.method = "GET";
1343 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101344 request.traffic_annotation =
1345 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141346
danakj1fd259a02016-04-16 03:17:091347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271349
[email protected]3a2d3662009-03-27 03:49:141350 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571351 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1352 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141353 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061354 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141355 };
Ryan Sleevib8d7ea02018-05-07 20:01:011356 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071357 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141358
[email protected]49639fa2011-12-20 23:22:411359 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141360
tfarina42834112016-09-22 13:38:201361 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011362 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141363
1364 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011365 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141366
bnc691fda62016-08-12 00:43:161367 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521368 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141369
wezca1070932016-05-26 20:30:521370 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141371 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1372
1373 std::string response_data;
bnc691fda62016-08-12 00:43:161374 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011375 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141376 EXPECT_EQ("hello world", response_data);
1377}
1378
Andrew Comminos517a92c2019-01-14 17:49:561379TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1380 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381381 base::TimeDelta::FromMilliseconds(10);
1382
1383 HttpRequestInfo request;
1384 request.method = "GET";
1385 request.url = GURL("http://www.foo.com/");
1386 request.traffic_annotation =
1387 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1388
1389 std::vector<MockWrite> data_writes = {
1390 MockWrite(ASYNC, 0,
1391 "GET / HTTP/1.1\r\n"
1392 "Host: www.foo.com\r\n"
1393 "Connection: keep-alive\r\n\r\n"),
1394 };
1395
1396 std::vector<MockRead> data_reads = {
1397 // Write one byte of the status line, followed by a pause.
1398 MockRead(ASYNC, 1, "H"),
1399 MockRead(ASYNC, ERR_IO_PENDING, 2),
1400 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1401 MockRead(ASYNC, 4, "hello world"),
1402 MockRead(SYNCHRONOUS, OK, 5),
1403 };
1404
1405 SequencedSocketData data(data_reads, data_writes);
1406 session_deps_.socket_factory->AddSocketDataProvider(&data);
1407
1408 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1409
1410 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1411
1412 TestCompletionCallback callback;
1413
1414 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1415 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1416
1417 data.RunUntilPaused();
1418 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561419 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381420 data.Resume();
1421
1422 rv = callback.WaitForResult();
1423 EXPECT_THAT(rv, IsOk());
1424
1425 const HttpResponseInfo* response = trans.GetResponseInfo();
1426 ASSERT_TRUE(response);
1427
1428 EXPECT_TRUE(response->headers);
1429 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1430
1431 LoadTimingInfo load_timing_info;
1432 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1433 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1434 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561435 // Ensure we didn't include the delay in the TTFB time.
1436 EXPECT_EQ(load_timing_info.receive_headers_start,
1437 load_timing_info.connect_timing.connect_end);
1438 // Ensure that the mock clock advanced at all.
1439 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1440 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381441
1442 std::string response_data;
1443 rv = ReadTransaction(&trans, &response_data);
1444 EXPECT_THAT(rv, IsOk());
1445 EXPECT_EQ("hello world", response_data);
1446}
1447
1448// Tests that the time-to-first-byte reported in a transaction's load timing
1449// info uses the first response, even if 1XX/informational.
1450void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561451 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381452 base::TimeDelta::FromMilliseconds(10);
1453
1454 HttpRequestInfo request;
1455 request.method = "GET";
1456 request.url = GURL("https://www.foo.com/");
1457 request.traffic_annotation =
1458 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1459
1460 SSLSocketDataProvider ssl(ASYNC, OK);
1461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1462
1463 std::vector<MockWrite> data_writes;
1464 std::vector<MockRead> data_reads;
1465
1466 spdy::SpdySerializedFrame spdy_req(
1467 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1468
1469 spdy::SpdyHeaderBlock spdy_resp1_headers;
1470 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1471 spdy::SpdySerializedFrame spdy_resp1(
1472 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1473 spdy::SpdySerializedFrame spdy_resp2(
1474 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1475 spdy::SpdySerializedFrame spdy_data(
1476 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1477
1478 if (use_spdy) {
1479 ssl.next_proto = kProtoHTTP2;
1480
1481 data_writes = {CreateMockWrite(spdy_req, 0)};
1482
1483 data_reads = {
1484 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1485 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1486 MockRead(SYNCHRONOUS, OK, 5),
1487 };
1488 } else {
1489 data_writes = {
1490 MockWrite(ASYNC, 0,
1491 "GET / HTTP/1.1\r\n"
1492 "Host: www.foo.com\r\n"
1493 "Connection: keep-alive\r\n\r\n"),
1494 };
1495
1496 data_reads = {
1497 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1498 MockRead(ASYNC, ERR_IO_PENDING, 2),
1499
1500 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1501 MockRead(ASYNC, 4, "hello world"),
1502 MockRead(SYNCHRONOUS, OK, 5),
1503 };
1504 }
1505
1506 SequencedSocketData data(data_reads, data_writes);
1507 session_deps_.socket_factory->AddSocketDataProvider(&data);
1508
1509 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1510
1511 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1512
1513 TestCompletionCallback callback;
1514
1515 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1516 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1517
1518 data.RunUntilPaused();
1519 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1520 // the delay before parsing the 200 response.
1521 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561522 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381523 data.Resume();
1524
1525 rv = callback.WaitForResult();
1526 EXPECT_THAT(rv, IsOk());
1527
1528 const HttpResponseInfo* response = trans.GetResponseInfo();
1529 ASSERT_TRUE(response);
1530
1531 LoadTimingInfo load_timing_info;
1532 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1533 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1534 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561535 // Ensure we didn't include the delay in the TTFB time.
1536 EXPECT_EQ(load_timing_info.receive_headers_start,
1537 load_timing_info.connect_timing.connect_end);
1538 // Ensure that the mock clock advanced at all.
1539 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1540 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381541
1542 std::string response_data;
1543 rv = ReadTransaction(&trans, &response_data);
1544 EXPECT_THAT(rv, IsOk());
1545 EXPECT_EQ("hello world", response_data);
1546}
1547
Andrew Comminos517a92c2019-01-14 17:49:561548TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381549 Check100ResponseTiming(false /* use_spdy */);
1550}
1551
Andrew Comminos517a92c2019-01-14 17:49:561552TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381553 Check100ResponseTiming(true /* use_spdy */);
1554}
1555
bncd16676a2016-07-20 16:23:011556TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081557 HttpRequestInfo request;
1558 request.method = "POST";
1559 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101560 request.traffic_annotation =
1561 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081562
danakj1fd259a02016-04-16 03:17:091563 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081565
1566 MockRead data_reads[] = {
1567 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1568 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381569 };
Ryan Sleevib8d7ea02018-05-07 20:01:011570 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081571 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381572
zmo9528c9f42015-08-04 22:12:081573 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381574
tfarina42834112016-09-22 13:38:201575 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011576 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381577
zmo9528c9f42015-08-04 22:12:081578 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011579 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381580
zmo9528c9f42015-08-04 22:12:081581 std::string response_data;
bnc691fda62016-08-12 00:43:161582 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011583 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081584 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381585}
1586
bncd16676a2016-07-20 16:23:011587TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381588 HttpRequestInfo request;
1589 request.method = "POST";
1590 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101591 request.traffic_annotation =
1592 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381593
danakj1fd259a02016-04-16 03:17:091594 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161595 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271596
[email protected]ee9410e72010-01-07 01:42:381597 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061598 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381599 };
Ryan Sleevib8d7ea02018-05-07 20:01:011600 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071601 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381602
[email protected]49639fa2011-12-20 23:22:411603 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381604
tfarina42834112016-09-22 13:38:201605 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011606 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381607
1608 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011609 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381610}
1611
[email protected]23e482282013-06-14 16:08:021612void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511613 const MockWrite* write_failure,
1614 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421615 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521616 request.method = "GET";
1617 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101618 request.traffic_annotation =
1619 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521620
Matt Muellerd9342e3a2019-11-26 01:41:141621 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071622 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091623 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271624
[email protected]202965992011-12-07 23:04:511625 // Written data for successfully sending both requests.
1626 MockWrite data1_writes[] = {
1627 MockWrite("GET / HTTP/1.1\r\n"
1628 "Host: www.foo.com\r\n"
1629 "Connection: keep-alive\r\n\r\n"),
1630 MockWrite("GET / HTTP/1.1\r\n"
1631 "Host: www.foo.com\r\n"
1632 "Connection: keep-alive\r\n\r\n")
1633 };
1634
1635 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521636 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351637 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1638 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061639 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521640 };
[email protected]202965992011-12-07 23:04:511641
1642 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491643 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511644 data1_writes[1] = *write_failure;
1645 } else {
1646 ASSERT_TRUE(read_failure);
1647 data1_reads[2] = *read_failure;
1648 }
1649
Ryan Sleevib8d7ea02018-05-07 20:01:011650 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071651 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521652
1653 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351654 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1655 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061656 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521657 };
Ryan Sleevib8d7ea02018-05-07 20:01:011658 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071659 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521660
thestig9d3bb0c2015-01-24 00:49:511661 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521662 "hello", "world"
1663 };
1664
mikecironef22f9812016-10-04 03:40:191665 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521666 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411667 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521668
bnc691fda62016-08-12 00:43:161669 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521670
tfarina42834112016-09-22 13:38:201671 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011672 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521673
1674 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011675 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521676
[email protected]58e32bb2013-01-21 18:23:251677 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161678 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251679 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1680 if (i == 0) {
1681 first_socket_log_id = load_timing_info.socket_log_id;
1682 } else {
1683 // The second request should be using a new socket.
1684 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1685 }
1686
bnc691fda62016-08-12 00:43:161687 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521688 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521689
wezca1070932016-05-26 20:30:521690 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471691 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251692 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521693
1694 std::string response_data;
bnc691fda62016-08-12 00:43:161695 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011696 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251697 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521698 }
1699}
[email protected]3d2a59b2008-09-26 19:44:251700
[email protected]a34f61ee2014-03-18 20:59:491701void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1702 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101703 const MockRead* read_failure,
1704 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491705 HttpRequestInfo request;
1706 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101707 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101708 request.traffic_annotation =
1709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491710
Matt Muellerd9342e3a2019-11-26 01:41:141711 RecordingTestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491712 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091713 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491714
[email protected]09356c652014-03-25 15:36:101715 SSLSocketDataProvider ssl1(ASYNC, OK);
1716 SSLSocketDataProvider ssl2(ASYNC, OK);
1717 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361718 ssl1.next_proto = kProtoHTTP2;
1719 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101720 }
1721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1722 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491723
[email protected]09356c652014-03-25 15:36:101724 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131725 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491726 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131727 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351728 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131729 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191730 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491731
[email protected]09356c652014-03-25 15:36:101732 // HTTP/1.1 versions of the request and response.
1733 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1734 "Host: www.foo.com\r\n"
1735 "Connection: keep-alive\r\n\r\n";
1736 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1737 const char kHttpData[] = "hello";
1738
1739 std::vector<MockRead> data1_reads;
1740 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491741 if (write_failure) {
1742 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101743 data1_writes.push_back(*write_failure);
1744 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491745 } else {
1746 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101747 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411748 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101749 } else {
1750 data1_writes.push_back(MockWrite(kHttpRequest));
1751 }
1752 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491753 }
1754
Ryan Sleevib8d7ea02018-05-07 20:01:011755 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491756 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1757
[email protected]09356c652014-03-25 15:36:101758 std::vector<MockRead> data2_reads;
1759 std::vector<MockWrite> data2_writes;
1760
1761 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411762 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101763
bncdf80d44fd2016-07-15 20:27:411764 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1765 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101766 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1767 } else {
1768 data2_writes.push_back(
1769 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1770
1771 data2_reads.push_back(
1772 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1773 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1774 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1775 }
Ryan Sleevib8d7ea02018-05-07 20:01:011776 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491777 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1778
1779 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591780 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491781 // Wait for the preconnect to complete.
1782 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1783 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231784 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491785
1786 // Make the request.
1787 TestCompletionCallback callback;
1788
bnc691fda62016-08-12 00:43:161789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491790
tfarina42834112016-09-22 13:38:201791 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011792 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491793
1794 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011795 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491796
1797 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161798 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101799 TestLoadTimingNotReused(
1800 load_timing_info,
1801 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491802
bnc691fda62016-08-12 00:43:161803 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521804 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491805
wezca1070932016-05-26 20:30:521806 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021807 if (response->was_fetched_via_spdy) {
1808 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1809 } else {
1810 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1811 }
[email protected]a34f61ee2014-03-18 20:59:491812
1813 std::string response_data;
bnc691fda62016-08-12 00:43:161814 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011815 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101816 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491817}
1818
Biljith Jayan45a41722017-08-16 18:43:141819// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181820// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141821// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1822TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1823 HttpRequestInfo request;
1824 request.method = "GET";
1825 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101826 request.traffic_annotation =
1827 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141828
1829 // Check whether we give up after the third try.
1830
1831 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131832 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141833 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131834 spdy::SpdySerializedFrame spdy_response_go_away(
1835 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011836 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1837 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141838
1839 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011840 StaticSocketDataProvider data1(data_read1, data_write);
1841 StaticSocketDataProvider data2(data_read1, data_write);
1842 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141843
1844 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1845 AddSSLSocketData();
1846 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1847 AddSSLSocketData();
1848 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1849 AddSSLSocketData();
1850
1851 TestCompletionCallback callback;
1852 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1853 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1854
1855 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1856 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1857
1858 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181859 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141860}
1861
1862TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1863 HttpRequestInfo request;
1864 request.method = "GET";
1865 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101866 request.traffic_annotation =
1867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141868
1869 // Check whether we try atleast thrice before giving up.
1870
1871 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131872 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141873 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131874 spdy::SpdySerializedFrame spdy_response_go_away(
1875 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011876 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1877 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141878
1879 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131880 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141881 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131882 spdy::SpdySerializedFrame spdy_data(
1883 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141884 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1885 CreateMockRead(spdy_data, 2)};
1886
1887 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011888 StaticSocketDataProvider data1(data_read1, data_write);
1889 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141890 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011891 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141892
1893 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1894 AddSSLSocketData();
1895 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1896 AddSSLSocketData();
1897 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1898 AddSSLSocketData();
1899
1900 TestCompletionCallback callback;
1901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1903
1904 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1906
1907 rv = callback.WaitForResult();
1908 EXPECT_THAT(rv, IsOk());
1909}
1910
bncd16676a2016-07-20 16:23:011911TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061912 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351913 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511914}
1915
bncd16676a2016-07-20 16:23:011916TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061917 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351918 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251919}
1920
bncd16676a2016-07-20 16:23:011921TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061922 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351923 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251924}
1925
[email protected]d58ceea82014-06-04 10:55:541926// Make sure that on a 408 response (Request Timeout), the request is retried,
1927// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011928TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541929 MockRead read_failure(SYNCHRONOUS,
1930 "HTTP/1.1 408 Request Timeout\r\n"
1931 "Connection: Keep-Alive\r\n"
1932 "Content-Length: 6\r\n\r\n"
1933 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351934 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541935}
1936
bncd16676a2016-07-20 16:23:011937TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491938 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351939 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491940}
1941
bncd16676a2016-07-20 16:23:011942TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491943 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351944 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491945}
1946
bncd16676a2016-07-20 16:23:011947TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491948 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351949 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101950}
1951
bncd16676a2016-07-20 16:23:011952TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101953 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351954 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101955}
1956
[email protected]d58ceea82014-06-04 10:55:541957// Make sure that on a 408 response (Request Timeout), the request is retried,
1958// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011959TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541960 MockRead read_failure(SYNCHRONOUS,
1961 "HTTP/1.1 408 Request Timeout\r\n"
1962 "Connection: Keep-Alive\r\n"
1963 "Content-Length: 6\r\n\r\n"
1964 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351965 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
1966 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:541967}
1968
bncd16676a2016-07-20 16:23:011969TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101970 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351971 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:101972}
1973
bncd16676a2016-07-20 16:23:011974TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101975 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351976 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101977}
1978
bncd16676a2016-07-20 16:23:011979TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101980 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351981 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101982}
1983
bncd16676a2016-07-20 16:23:011984TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101985 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351986 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491987}
1988
bncd16676a2016-07-20 16:23:011989TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421990 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251991 request.method = "GET";
bncce36dca22015-04-21 22:11:231992 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101993 request.traffic_annotation =
1994 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:251995
danakj1fd259a02016-04-16 03:17:091996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161997 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271998
[email protected]3d2a59b2008-09-26 19:44:251999 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062000 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352001 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2002 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062003 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252004 };
Ryan Sleevib8d7ea02018-05-07 20:01:012005 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072006 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252007
[email protected]49639fa2011-12-20 23:22:412008 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252009
tfarina42834112016-09-22 13:38:202010 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252012
2013 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012014 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592015
2016 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162017 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592018 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252019}
2020
2021// What do various browsers do when the server closes a non-keepalive
2022// connection without sending any response header or body?
2023//
2024// IE7: error page
2025// Safari 3.1.2 (Windows): error page
2026// Firefox 3.0.1: blank page
2027// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422028// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2029// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012030TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252031 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062032 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352033 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2034 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062035 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252036 };
Ryan Sleevib8d7ea02018-05-07 20:01:012037 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012038 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252039}
[email protected]1826a402014-01-08 15:40:482040
[email protected]7a5378b2012-11-04 03:25:172041// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2042// tests. There was a bug causing HttpNetworkTransaction to hang in the
2043// destructor in such situations.
2044// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012045TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172046 HttpRequestInfo request;
2047 request.method = "GET";
bncce36dca22015-04-21 22:11:232048 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102049 request.traffic_annotation =
2050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172051
danakj1fd259a02016-04-16 03:17:092052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582053 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192054 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172055
2056 MockRead data_reads[] = {
2057 MockRead("HTTP/1.0 200 OK\r\n"),
2058 MockRead("Connection: keep-alive\r\n"),
2059 MockRead("Content-Length: 100\r\n\r\n"),
2060 MockRead("hello"),
2061 MockRead(SYNCHRONOUS, 0),
2062 };
Ryan Sleevib8d7ea02018-05-07 20:01:012063 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072064 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172065
2066 TestCompletionCallback callback;
2067
tfarina42834112016-09-22 13:38:202068 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012069 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172070
2071 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012072 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172073
Victor Costan9c7302b2018-08-27 16:39:442074 scoped_refptr<IOBufferWithSize> io_buf =
2075 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502076 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172077 if (rv == ERR_IO_PENDING)
2078 rv = callback.WaitForResult();
2079 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502080 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012081 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172082
2083 trans.reset();
fdoray92e35a72016-06-10 15:54:552084 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172085 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2086}
2087
bncd16676a2016-07-20 16:23:012088TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[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(SYNCHRONOUS, 0),
2104 };
Ryan Sleevib8d7ea02018-05-07 20:01:012105 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072106 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172107
2108 TestCompletionCallback callback;
2109
tfarina42834112016-09-22 13:38:202110 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012111 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172112
2113 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012114 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172115
Victor Costan9c7302b2018-08-27 16:39:442116 scoped_refptr<IOBufferWithSize> io_buf(
2117 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502118 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172119 if (rv == ERR_IO_PENDING)
2120 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012121 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172122
2123 trans.reset();
fdoray92e35a72016-06-10 15:54:552124 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172125 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2126}
2127
[email protected]0b0bf032010-09-21 18:08:502128// Test that we correctly reuse a keep-alive connection after not explicitly
2129// reading the body.
bncd16676a2016-07-20 16:23:012130TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132131 HttpRequestInfo request;
2132 request.method = "GET";
2133 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102134 request.traffic_annotation =
2135 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132136
Matt Muellerd9342e3a2019-11-26 01:41:142137 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072138 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092139 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272140
mmenkecc2298e2015-12-07 18:20:182141 const char* request_data =
2142 "GET / HTTP/1.1\r\n"
2143 "Host: www.foo.com\r\n"
2144 "Connection: keep-alive\r\n\r\n";
2145 MockWrite data_writes[] = {
2146 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2147 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2148 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2149 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2150 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2151 };
2152
[email protected]0b0bf032010-09-21 18:08:502153 // Note that because all these reads happen in the same
2154 // StaticSocketDataProvider, it shows that the same socket is being reused for
2155 // all transactions.
mmenkecc2298e2015-12-07 18:20:182156 MockRead data_reads[] = {
2157 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2158 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2159 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2160 MockRead(ASYNC, 7,
2161 "HTTP/1.1 302 Found\r\n"
2162 "Content-Length: 0\r\n\r\n"),
2163 MockRead(ASYNC, 9,
2164 "HTTP/1.1 302 Found\r\n"
2165 "Content-Length: 5\r\n\r\n"
2166 "hello"),
2167 MockRead(ASYNC, 11,
2168 "HTTP/1.1 301 Moved Permanently\r\n"
2169 "Content-Length: 0\r\n\r\n"),
2170 MockRead(ASYNC, 13,
2171 "HTTP/1.1 301 Moved Permanently\r\n"
2172 "Content-Length: 5\r\n\r\n"
2173 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132174
mmenkecc2298e2015-12-07 18:20:182175 // In the next two rounds, IsConnectedAndIdle returns false, due to
2176 // the set_busy_before_sync_reads(true) call, while the
2177 // HttpNetworkTransaction is being shut down, but the socket is still
2178 // reuseable. See http://crbug.com/544255.
2179 MockRead(ASYNC, 15,
2180 "HTTP/1.1 200 Hunky-Dory\r\n"
2181 "Content-Length: 5\r\n\r\n"),
2182 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132183
mmenkecc2298e2015-12-07 18:20:182184 MockRead(ASYNC, 18,
2185 "HTTP/1.1 200 Hunky-Dory\r\n"
2186 "Content-Length: 5\r\n\r\n"
2187 "he"),
2188 MockRead(SYNCHRONOUS, 19, "llo"),
2189
2190 // The body of the final request is actually read.
2191 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2192 MockRead(ASYNC, 22, "hello"),
2193 };
Ryan Sleevib8d7ea02018-05-07 20:01:012194 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182195 data.set_busy_before_sync_reads(true);
2196 session_deps_.socket_factory->AddSocketDataProvider(&data);
2197
Avi Drissman4365a4782018-12-28 19:26:242198 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502199 std::string response_lines[kNumUnreadBodies];
2200
mikecironef22f9812016-10-04 03:40:192201 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182202 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412203 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132204
Jeremy Roman0579ed62017-08-29 15:56:192205 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582206 session.get());
[email protected]fc31d6a42010-06-24 18:05:132207
tfarina42834112016-09-22 13:38:202208 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012209 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132210
[email protected]58e32bb2013-01-21 18:23:252211 LoadTimingInfo load_timing_info;
2212 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2213 if (i == 0) {
2214 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2215 first_socket_log_id = load_timing_info.socket_log_id;
2216 } else {
2217 TestLoadTimingReused(load_timing_info);
2218 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2219 }
2220
[email protected]fc31d6a42010-06-24 18:05:132221 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182222 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132223
mmenkecc2298e2015-12-07 18:20:182224 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502225 response_lines[i] = response->headers->GetStatusLine();
2226
mmenkecc2298e2015-12-07 18:20:182227 // Delete the transaction without reading the response bodies. Then spin
2228 // the message loop, so the response bodies are drained.
2229 trans.reset();
2230 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132231 }
[email protected]0b0bf032010-09-21 18:08:502232
2233 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182234 "HTTP/1.1 204 No Content",
2235 "HTTP/1.1 205 Reset Content",
2236 "HTTP/1.1 304 Not Modified",
2237 "HTTP/1.1 302 Found",
2238 "HTTP/1.1 302 Found",
2239 "HTTP/1.1 301 Moved Permanently",
2240 "HTTP/1.1 301 Moved Permanently",
2241 "HTTP/1.1 200 Hunky-Dory",
2242 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502243 };
2244
Avi Drissman4365a4782018-12-28 19:26:242245 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272246 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502247
2248 for (int i = 0; i < kNumUnreadBodies; ++i)
2249 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2250
[email protected]49639fa2011-12-20 23:22:412251 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162252 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202253 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012254 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162255 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182256 ASSERT_TRUE(response);
2257 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502258 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2259 std::string response_data;
bnc691fda62016-08-12 00:43:162260 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012261 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502262 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132263}
2264
mmenke5f94fda2016-06-02 20:54:132265// Sockets that receive extra data after a response is complete should not be
2266// reused.
bncd16676a2016-07-20 16:23:012267TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132268 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2269 MockWrite data_writes1[] = {
2270 MockWrite("HEAD / HTTP/1.1\r\n"
2271 "Host: www.borked.com\r\n"
2272 "Connection: keep-alive\r\n\r\n"),
2273 };
2274
2275 MockRead data_reads1[] = {
2276 MockRead("HTTP/1.1 200 OK\r\n"
2277 "Connection: keep-alive\r\n"
2278 "Content-Length: 22\r\n\r\n"
2279 "This server is borked."),
2280 };
2281
2282 MockWrite data_writes2[] = {
2283 MockWrite("GET /foo HTTP/1.1\r\n"
2284 "Host: www.borked.com\r\n"
2285 "Connection: keep-alive\r\n\r\n"),
2286 };
2287
2288 MockRead data_reads2[] = {
2289 MockRead("HTTP/1.1 200 OK\r\n"
2290 "Content-Length: 3\r\n\r\n"
2291 "foo"),
2292 };
Ryan Sleevib8d7ea02018-05-07 20:01:012293 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132294 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012295 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132296 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2297
2298 TestCompletionCallback callback;
2299 HttpRequestInfo request1;
2300 request1.method = "HEAD";
2301 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102302 request1.traffic_annotation =
2303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132304
bnc87dcefc2017-05-25 12:47:582305 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192306 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202307 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012308 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132309
2310 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2311 ASSERT_TRUE(response1);
2312 ASSERT_TRUE(response1->headers);
2313 EXPECT_EQ(200, response1->headers->response_code());
2314 EXPECT_TRUE(response1->headers->IsKeepAlive());
2315
2316 std::string response_data1;
robpercival214763f2016-07-01 23:27:012317 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132318 EXPECT_EQ("", response_data1);
2319 // Deleting the transaction attempts to release the socket back into the
2320 // socket pool.
2321 trans1.reset();
2322
2323 HttpRequestInfo request2;
2324 request2.method = "GET";
2325 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102326 request2.traffic_annotation =
2327 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132328
bnc87dcefc2017-05-25 12:47:582329 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192330 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202331 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012332 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132333
2334 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2335 ASSERT_TRUE(response2);
2336 ASSERT_TRUE(response2->headers);
2337 EXPECT_EQ(200, response2->headers->response_code());
2338
2339 std::string response_data2;
robpercival214763f2016-07-01 23:27:012340 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132341 EXPECT_EQ("foo", response_data2);
2342}
2343
bncd16676a2016-07-20 16:23:012344TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132345 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2346 MockWrite data_writes1[] = {
2347 MockWrite("GET / HTTP/1.1\r\n"
2348 "Host: www.borked.com\r\n"
2349 "Connection: keep-alive\r\n\r\n"),
2350 };
2351
2352 MockRead data_reads1[] = {
2353 MockRead("HTTP/1.1 200 OK\r\n"
2354 "Connection: keep-alive\r\n"
2355 "Content-Length: 22\r\n\r\n"
2356 "This server is borked."
2357 "Bonus data!"),
2358 };
2359
2360 MockWrite data_writes2[] = {
2361 MockWrite("GET /foo HTTP/1.1\r\n"
2362 "Host: www.borked.com\r\n"
2363 "Connection: keep-alive\r\n\r\n"),
2364 };
2365
2366 MockRead data_reads2[] = {
2367 MockRead("HTTP/1.1 200 OK\r\n"
2368 "Content-Length: 3\r\n\r\n"
2369 "foo"),
2370 };
Ryan Sleevib8d7ea02018-05-07 20:01:012371 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132372 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012373 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132374 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2375
2376 TestCompletionCallback callback;
2377 HttpRequestInfo request1;
2378 request1.method = "GET";
2379 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102380 request1.traffic_annotation =
2381 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132382
bnc87dcefc2017-05-25 12:47:582383 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192384 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202385 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012386 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132387
2388 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2389 ASSERT_TRUE(response1);
2390 ASSERT_TRUE(response1->headers);
2391 EXPECT_EQ(200, response1->headers->response_code());
2392 EXPECT_TRUE(response1->headers->IsKeepAlive());
2393
2394 std::string response_data1;
robpercival214763f2016-07-01 23:27:012395 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132396 EXPECT_EQ("This server is borked.", response_data1);
2397 // Deleting the transaction attempts to release the socket back into the
2398 // socket pool.
2399 trans1.reset();
2400
2401 HttpRequestInfo request2;
2402 request2.method = "GET";
2403 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102404 request2.traffic_annotation =
2405 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132406
bnc87dcefc2017-05-25 12:47:582407 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192408 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202409 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012410 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132411
2412 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2413 ASSERT_TRUE(response2);
2414 ASSERT_TRUE(response2->headers);
2415 EXPECT_EQ(200, response2->headers->response_code());
2416
2417 std::string response_data2;
robpercival214763f2016-07-01 23:27:012418 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132419 EXPECT_EQ("foo", response_data2);
2420}
2421
bncd16676a2016-07-20 16:23:012422TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132423 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2424 MockWrite data_writes1[] = {
2425 MockWrite("GET / HTTP/1.1\r\n"
2426 "Host: www.borked.com\r\n"
2427 "Connection: keep-alive\r\n\r\n"),
2428 };
2429
2430 MockRead data_reads1[] = {
2431 MockRead("HTTP/1.1 200 OK\r\n"
2432 "Connection: keep-alive\r\n"
2433 "Transfer-Encoding: chunked\r\n\r\n"),
2434 MockRead("16\r\nThis server is borked.\r\n"),
2435 MockRead("0\r\n\r\nBonus data!"),
2436 };
2437
2438 MockWrite data_writes2[] = {
2439 MockWrite("GET /foo HTTP/1.1\r\n"
2440 "Host: www.borked.com\r\n"
2441 "Connection: keep-alive\r\n\r\n"),
2442 };
2443
2444 MockRead data_reads2[] = {
2445 MockRead("HTTP/1.1 200 OK\r\n"
2446 "Content-Length: 3\r\n\r\n"
2447 "foo"),
2448 };
Ryan Sleevib8d7ea02018-05-07 20:01:012449 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132450 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012451 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132452 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2453
2454 TestCompletionCallback callback;
2455 HttpRequestInfo request1;
2456 request1.method = "GET";
2457 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102458 request1.traffic_annotation =
2459 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132460
bnc87dcefc2017-05-25 12:47:582461 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192462 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202463 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012464 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132465
2466 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2467 ASSERT_TRUE(response1);
2468 ASSERT_TRUE(response1->headers);
2469 EXPECT_EQ(200, response1->headers->response_code());
2470 EXPECT_TRUE(response1->headers->IsKeepAlive());
2471
2472 std::string response_data1;
robpercival214763f2016-07-01 23:27:012473 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132474 EXPECT_EQ("This server is borked.", response_data1);
2475 // Deleting the transaction attempts to release the socket back into the
2476 // socket pool.
2477 trans1.reset();
2478
2479 HttpRequestInfo request2;
2480 request2.method = "GET";
2481 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102482 request2.traffic_annotation =
2483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132484
bnc87dcefc2017-05-25 12:47:582485 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192486 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202487 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012488 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132489
2490 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2491 ASSERT_TRUE(response2);
2492 ASSERT_TRUE(response2->headers);
2493 EXPECT_EQ(200, response2->headers->response_code());
2494
2495 std::string response_data2;
robpercival214763f2016-07-01 23:27:012496 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132497 EXPECT_EQ("foo", response_data2);
2498}
2499
2500// This is a little different from the others - it tests the case that the
2501// HttpStreamParser doesn't know if there's extra data on a socket or not when
2502// the HttpNetworkTransaction is torn down, because the response body hasn't
2503// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012504TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132505 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2506 MockWrite data_writes1[] = {
2507 MockWrite("GET / HTTP/1.1\r\n"
2508 "Host: www.borked.com\r\n"
2509 "Connection: keep-alive\r\n\r\n"),
2510 };
2511
2512 MockRead data_reads1[] = {
2513 MockRead("HTTP/1.1 200 OK\r\n"
2514 "Connection: keep-alive\r\n"
2515 "Transfer-Encoding: chunked\r\n\r\n"),
2516 MockRead("16\r\nThis server is borked.\r\n"),
2517 MockRead("0\r\n\r\nBonus data!"),
2518 };
Ryan Sleevib8d7ea02018-05-07 20:01:012519 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132520 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2521
2522 TestCompletionCallback callback;
2523 HttpRequestInfo request1;
2524 request1.method = "GET";
2525 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102526 request1.traffic_annotation =
2527 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132528
bnc87dcefc2017-05-25 12:47:582529 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192530 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582531 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012532 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132533
bnc87dcefc2017-05-25 12:47:582534 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132535 ASSERT_TRUE(response1);
2536 ASSERT_TRUE(response1->headers);
2537 EXPECT_EQ(200, response1->headers->response_code());
2538 EXPECT_TRUE(response1->headers->IsKeepAlive());
2539
2540 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2541 // response body.
bnc87dcefc2017-05-25 12:47:582542 trans.reset();
mmenke5f94fda2016-06-02 20:54:132543
2544 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2545 // socket can't be reused, rather than returning it to the socket pool.
2546 base::RunLoop().RunUntilIdle();
2547
2548 // There should be no idle sockets in the pool.
2549 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2550}
2551
[email protected]038e9a32008-10-08 22:40:162552// Test the request-challenge-retry sequence for basic auth.
2553// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012554TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422555 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162556 request.method = "GET";
bncce36dca22015-04-21 22:11:232557 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102558 request.traffic_annotation =
2559 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162560
Matt Muellerd9342e3a2019-11-26 01:41:142561 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072562 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092563 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272565
[email protected]f9ee6b52008-11-08 06:46:232566 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232567 MockWrite(
2568 "GET / HTTP/1.1\r\n"
2569 "Host: www.example.org\r\n"
2570 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232571 };
2572
[email protected]038e9a32008-10-08 22:40:162573 MockRead data_reads1[] = {
2574 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2575 // Give a couple authenticate options (only the middle one is actually
2576 // supported).
[email protected]22927ad2009-09-21 19:56:192577 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162578 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2579 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2580 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2581 // Large content-length -- won't matter, as connection will be reset.
2582 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062583 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162584 };
2585
2586 // After calling trans->RestartWithAuth(), this is the request we should
2587 // be issuing -- the final header line contains the credentials.
2588 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232589 MockWrite(
2590 "GET / HTTP/1.1\r\n"
2591 "Host: www.example.org\r\n"
2592 "Connection: keep-alive\r\n"
2593 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162594 };
2595
2596 // Lastly, the server responds with the actual content.
2597 MockRead data_reads2[] = {
2598 MockRead("HTTP/1.0 200 OK\r\n"),
2599 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2600 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062601 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162602 };
2603
Ryan Sleevib8d7ea02018-05-07 20:01:012604 StaticSocketDataProvider data1(data_reads1, data_writes1);
2605 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072606 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2607 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162608
[email protected]49639fa2011-12-20 23:22:412609 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162610
tfarina42834112016-09-22 13:38:202611 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012612 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162613
2614 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012615 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162616
[email protected]58e32bb2013-01-21 18:23:252617 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162618 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252619 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2620
Ryan Sleevib8d7ea02018-05-07 20:01:012621 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162622 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012623 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162624 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192625
bnc691fda62016-08-12 00:43:162626 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522627 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582628 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162629
[email protected]49639fa2011-12-20 23:22:412630 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162631
bnc691fda62016-08-12 00:43:162632 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012633 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162634
2635 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012636 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162637
[email protected]58e32bb2013-01-21 18:23:252638 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162639 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252640 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2641 // The load timing after restart should have a new socket ID, and times after
2642 // those of the first load timing.
2643 EXPECT_LE(load_timing_info1.receive_headers_end,
2644 load_timing_info2.connect_timing.connect_start);
2645 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2646
Ryan Sleevib8d7ea02018-05-07 20:01:012647 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162648 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012649 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162650 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192651
bnc691fda62016-08-12 00:43:162652 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522653 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582654 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162655 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162656}
2657
ttuttled9dbc652015-09-29 20:00:592658// Test the request-challenge-retry sequence for basic auth.
2659// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012660TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592661 HttpRequestInfo request;
2662 request.method = "GET";
2663 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102664 request.traffic_annotation =
2665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592666
Matt Muellerd9342e3a2019-11-26 01:41:142667 RecordingTestNetLog log;
ttuttled9dbc652015-09-29 20:00:592668 MockHostResolver* resolver = new MockHostResolver();
2669 session_deps_.net_log = &log;
2670 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092671 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162672 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592673
2674 resolver->rules()->ClearRules();
2675 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2676
2677 MockWrite data_writes1[] = {
2678 MockWrite("GET / HTTP/1.1\r\n"
2679 "Host: www.example.org\r\n"
2680 "Connection: keep-alive\r\n\r\n"),
2681 };
2682
2683 MockRead data_reads1[] = {
2684 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2685 // Give a couple authenticate options (only the middle one is actually
2686 // supported).
2687 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2689 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2690 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2691 // Large content-length -- won't matter, as connection will be reset.
2692 MockRead("Content-Length: 10000\r\n\r\n"),
2693 MockRead(SYNCHRONOUS, ERR_FAILED),
2694 };
2695
2696 // After calling trans->RestartWithAuth(), this is the request we should
2697 // be issuing -- the final header line contains the credentials.
2698 MockWrite data_writes2[] = {
2699 MockWrite("GET / HTTP/1.1\r\n"
2700 "Host: www.example.org\r\n"
2701 "Connection: keep-alive\r\n"
2702 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2703 };
2704
2705 // Lastly, the server responds with the actual content.
2706 MockRead data_reads2[] = {
2707 MockRead("HTTP/1.0 200 OK\r\n"),
2708 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2709 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2710 };
2711
Ryan Sleevib8d7ea02018-05-07 20:01:012712 StaticSocketDataProvider data1(data_reads1, data_writes1);
2713 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592714 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2715 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2716
2717 TestCompletionCallback callback1;
2718
bnc691fda62016-08-12 00:43:162719 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202720 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592721
2722 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162723 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592724 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2725
Ryan Sleevib8d7ea02018-05-07 20:01:012726 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162727 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012728 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162729 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592730
bnc691fda62016-08-12 00:43:162731 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592732 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582733 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592734
2735 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162736 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592737 ASSERT_FALSE(endpoint.address().empty());
2738 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2739
2740 resolver->rules()->ClearRules();
2741 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2742
2743 TestCompletionCallback callback2;
2744
bnc691fda62016-08-12 00:43:162745 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592746 AuthCredentials(kFoo, kBar), callback2.callback())));
2747
2748 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162749 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592750 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2751 // The load timing after restart should have a new socket ID, and times after
2752 // those of the first load timing.
2753 EXPECT_LE(load_timing_info1.receive_headers_end,
2754 load_timing_info2.connect_timing.connect_start);
2755 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2756
Ryan Sleevib8d7ea02018-05-07 20:01:012757 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162758 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012759 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162760 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592761
bnc691fda62016-08-12 00:43:162762 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592763 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582764 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592765 EXPECT_EQ(100, response->headers->GetContentLength());
2766
bnc691fda62016-08-12 00:43:162767 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592768 ASSERT_FALSE(endpoint.address().empty());
2769 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2770}
2771
David Benjamin83ddfb32018-03-30 01:07:522772// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2773// will eventually give up.
2774TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2775 HttpRequestInfo request;
2776 request.method = "GET";
2777 request.url = GURL("http://www.example.org/");
2778 request.traffic_annotation =
2779 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2780
Matt Muellerd9342e3a2019-11-26 01:41:142781 RecordingTestNetLog log;
David Benjamin83ddfb32018-03-30 01:07:522782 session_deps_.net_log = &log;
2783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2785
2786 MockWrite data_writes[] = {
2787 MockWrite("GET / HTTP/1.1\r\n"
2788 "Host: www.example.org\r\n"
2789 "Connection: keep-alive\r\n\r\n"),
2790 };
2791
2792 MockRead data_reads[] = {
2793 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2794 // Give a couple authenticate options (only the middle one is actually
2795 // supported).
2796 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2797 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2798 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2800 // Large content-length -- won't matter, as connection will be reset.
2801 MockRead("Content-Length: 10000\r\n\r\n"),
2802 MockRead(SYNCHRONOUS, ERR_FAILED),
2803 };
2804
2805 // After calling trans->RestartWithAuth(), this is the request we should
2806 // be issuing -- the final header line contains the credentials.
2807 MockWrite data_writes_restart[] = {
2808 MockWrite("GET / HTTP/1.1\r\n"
2809 "Host: www.example.org\r\n"
2810 "Connection: keep-alive\r\n"
2811 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2812 };
2813
Ryan Sleevib8d7ea02018-05-07 20:01:012814 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522815 session_deps_.socket_factory->AddSocketDataProvider(&data);
2816
2817 TestCompletionCallback callback;
2818 int rv = callback.GetResult(
2819 trans.Start(&request, callback.callback(), NetLogWithSource()));
2820
2821 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2822 for (int i = 0; i < 32; i++) {
2823 // Check the previous response was a 401.
2824 EXPECT_THAT(rv, IsOk());
2825 const HttpResponseInfo* response = trans.GetResponseInfo();
2826 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582827 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522828
2829 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012830 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522831 session_deps_.socket_factory->AddSocketDataProvider(
2832 data_restarts.back().get());
2833 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2834 callback.callback()));
2835 }
2836
2837 // After too many tries, the transaction should have given up.
2838 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2839}
2840
bncd16676a2016-07-20 16:23:012841TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462842 HttpRequestInfo request;
2843 request.method = "GET";
bncce36dca22015-04-21 22:11:232844 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292845 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:102846 request.traffic_annotation =
2847 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462848
danakj1fd259a02016-04-16 03:17:092849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162850 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272851
[email protected]861fcd52009-08-26 02:33:462852 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232853 MockWrite(
2854 "GET / HTTP/1.1\r\n"
2855 "Host: www.example.org\r\n"
2856 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462857 };
2858
2859 MockRead data_reads[] = {
2860 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2861 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2862 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2863 // Large content-length -- won't matter, as connection will be reset.
2864 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062865 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462866 };
2867
Ryan Sleevib8d7ea02018-05-07 20:01:012868 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072869 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412870 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462871
tfarina42834112016-09-22 13:38:202872 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462874
2875 rv = callback.WaitForResult();
2876 EXPECT_EQ(0, rv);
2877
Ryan Sleevib8d7ea02018-05-07 20:01:012878 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162879 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012880 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162881 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192882
bnc691fda62016-08-12 00:43:162883 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522884 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582885 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462886}
2887
[email protected]2d2697f92009-02-18 21:00:322888// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2889// connection.
bncd16676a2016-07-20 16:23:012890TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182891 // On the second pass, the body read of the auth challenge is synchronous, so
2892 // IsConnectedAndIdle returns false. The socket should still be drained and
2893 // reused. See http://crbug.com/544255.
2894 for (int i = 0; i < 2; ++i) {
2895 HttpRequestInfo request;
2896 request.method = "GET";
2897 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102898 request.traffic_annotation =
2899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322900
Matt Muellerd9342e3a2019-11-26 01:41:142901 RecordingTestNetLog log;
mmenkecc2298e2015-12-07 18:20:182902 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092903 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272904
mmenkecc2298e2015-12-07 18:20:182905 MockWrite data_writes[] = {
2906 MockWrite(ASYNC, 0,
2907 "GET / HTTP/1.1\r\n"
2908 "Host: www.example.org\r\n"
2909 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322910
bnc691fda62016-08-12 00:43:162911 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182912 // be issuing -- the final header line contains the credentials.
2913 MockWrite(ASYNC, 6,
2914 "GET / HTTP/1.1\r\n"
2915 "Host: www.example.org\r\n"
2916 "Connection: keep-alive\r\n"
2917 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2918 };
[email protected]2d2697f92009-02-18 21:00:322919
mmenkecc2298e2015-12-07 18:20:182920 MockRead data_reads[] = {
2921 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2922 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2923 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2924 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2925 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322926
mmenkecc2298e2015-12-07 18:20:182927 // Lastly, the server responds with the actual content.
2928 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2929 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2930 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2931 MockRead(ASYNC, 10, "Hello"),
2932 };
[email protected]2d2697f92009-02-18 21:00:322933
Ryan Sleevib8d7ea02018-05-07 20:01:012934 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182935 data.set_busy_before_sync_reads(true);
2936 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462937
mmenkecc2298e2015-12-07 18:20:182938 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322939
bnc691fda62016-08-12 00:43:162940 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202941 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012942 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322943
mmenkecc2298e2015-12-07 18:20:182944 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162945 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182946 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322947
bnc691fda62016-08-12 00:43:162948 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182949 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582950 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322951
mmenkecc2298e2015-12-07 18:20:182952 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252953
bnc691fda62016-08-12 00:43:162954 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2955 callback2.callback());
robpercival214763f2016-07-01 23:27:012956 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322957
mmenkecc2298e2015-12-07 18:20:182958 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162959 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:182960 TestLoadTimingReused(load_timing_info2);
2961 // The load timing after restart should have the same socket ID, and times
2962 // those of the first load timing.
2963 EXPECT_LE(load_timing_info1.receive_headers_end,
2964 load_timing_info2.send_start);
2965 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322966
bnc691fda62016-08-12 00:43:162967 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182968 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582969 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:182970 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322971
mmenkecc2298e2015-12-07 18:20:182972 std::string response_data;
bnc691fda62016-08-12 00:43:162973 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322974
Ryan Sleevib8d7ea02018-05-07 20:01:012975 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162976 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012977 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162978 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:182979 }
[email protected]2d2697f92009-02-18 21:00:322980}
2981
2982// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2983// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012984TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422985 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322986 request.method = "GET";
bncce36dca22015-04-21 22:11:232987 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102988 request.traffic_annotation =
2989 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322990
danakj1fd259a02016-04-16 03:17:092991 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272992
[email protected]2d2697f92009-02-18 21:00:322993 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:162994 MockWrite("GET / HTTP/1.1\r\n"
2995 "Host: www.example.org\r\n"
2996 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322997
bnc691fda62016-08-12 00:43:162998 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:232999 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163000 MockWrite("GET / HTTP/1.1\r\n"
3001 "Host: www.example.org\r\n"
3002 "Connection: keep-alive\r\n"
3003 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323004 };
3005
[email protected]2d2697f92009-02-18 21:00:323006 MockRead data_reads1[] = {
3007 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3008 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313009 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323010
3011 // Lastly, the server responds with the actual content.
3012 MockRead("HTTP/1.1 200 OK\r\n"),
3013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503014 MockRead("Content-Length: 5\r\n\r\n"),
3015 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323016 };
3017
[email protected]2d0a4f92011-05-05 16:38:463018 // An incorrect reconnect would cause this to be read.
3019 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063020 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463021 };
3022
Ryan Sleevib8d7ea02018-05-07 20:01:013023 StaticSocketDataProvider data1(data_reads1, data_writes1);
3024 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073025 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3026 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323027
[email protected]49639fa2011-12-20 23:22:413028 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323029
bnc691fda62016-08-12 00:43:163030 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203031 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013032 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323033
3034 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013035 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323036
bnc691fda62016-08-12 00:43:163037 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523038 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583039 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323040
[email protected]49639fa2011-12-20 23:22:413041 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323042
bnc691fda62016-08-12 00:43:163043 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323045
3046 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013047 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323048
bnc691fda62016-08-12 00:43:163049 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523050 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583051 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503052 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323053}
3054
3055// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3056// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013057TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423058 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323059 request.method = "GET";
bncce36dca22015-04-21 22:11:233060 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103061 request.traffic_annotation =
3062 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323063
danakj1fd259a02016-04-16 03:17:093064 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273065
[email protected]2d2697f92009-02-18 21:00:323066 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163067 MockWrite("GET / HTTP/1.1\r\n"
3068 "Host: www.example.org\r\n"
3069 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323070
bnc691fda62016-08-12 00:43:163071 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233072 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163073 MockWrite("GET / HTTP/1.1\r\n"
3074 "Host: www.example.org\r\n"
3075 "Connection: keep-alive\r\n"
3076 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323077 };
3078
3079 // Respond with 5 kb of response body.
3080 std::string large_body_string("Unauthorized");
3081 large_body_string.append(5 * 1024, ' ');
3082 large_body_string.append("\r\n");
3083
3084 MockRead data_reads1[] = {
3085 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3086 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3087 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3088 // 5134 = 12 + 5 * 1024 + 2
3089 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063090 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323091
3092 // Lastly, the server responds with the actual content.
3093 MockRead("HTTP/1.1 200 OK\r\n"),
3094 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503095 MockRead("Content-Length: 5\r\n\r\n"),
3096 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323097 };
3098
[email protected]2d0a4f92011-05-05 16:38:463099 // An incorrect reconnect would cause this to be read.
3100 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063101 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463102 };
3103
Ryan Sleevib8d7ea02018-05-07 20:01:013104 StaticSocketDataProvider data1(data_reads1, data_writes1);
3105 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073106 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3107 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323108
[email protected]49639fa2011-12-20 23:22:413109 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323110
bnc691fda62016-08-12 00:43:163111 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203112 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013113 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323114
3115 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013116 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323117
bnc691fda62016-08-12 00:43:163118 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523119 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583120 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323121
[email protected]49639fa2011-12-20 23:22:413122 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323123
bnc691fda62016-08-12 00:43:163124 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013125 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323126
3127 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013128 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323129
bnc691fda62016-08-12 00:43:163130 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523131 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583132 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503133 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323134}
3135
3136// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313137// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013138TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313139 HttpRequestInfo request;
3140 request.method = "GET";
bncce36dca22015-04-21 22:11:233141 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103142 request.traffic_annotation =
3143 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313144
danakj1fd259a02016-04-16 03:17:093145 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273146
[email protected]11203f012009-11-12 23:02:313147 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233148 MockWrite(
3149 "GET / HTTP/1.1\r\n"
3150 "Host: www.example.org\r\n"
3151 "Connection: keep-alive\r\n\r\n"),
3152 // This simulates the seemingly successful write to a closed connection
3153 // if the bug is not fixed.
3154 MockWrite(
3155 "GET / HTTP/1.1\r\n"
3156 "Host: www.example.org\r\n"
3157 "Connection: keep-alive\r\n"
3158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313159 };
3160
3161 MockRead data_reads1[] = {
3162 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3165 MockRead("Content-Length: 14\r\n\r\n"),
3166 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063167 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313168 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063169 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313170 };
3171
bnc691fda62016-08-12 00:43:163172 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313173 // be issuing -- the final header line contains the credentials.
3174 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233175 MockWrite(
3176 "GET / HTTP/1.1\r\n"
3177 "Host: www.example.org\r\n"
3178 "Connection: keep-alive\r\n"
3179 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313180 };
3181
3182 // Lastly, the server responds with the actual content.
3183 MockRead data_reads2[] = {
3184 MockRead("HTTP/1.1 200 OK\r\n"),
3185 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503186 MockRead("Content-Length: 5\r\n\r\n"),
3187 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313188 };
3189
Ryan Sleevib8d7ea02018-05-07 20:01:013190 StaticSocketDataProvider data1(data_reads1, data_writes1);
3191 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073192 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3193 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313194
[email protected]49639fa2011-12-20 23:22:413195 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313196
bnc691fda62016-08-12 00:43:163197 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203198 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013199 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313200
3201 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013202 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313203
bnc691fda62016-08-12 00:43:163204 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523205 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583206 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313207
[email protected]49639fa2011-12-20 23:22:413208 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313209
bnc691fda62016-08-12 00:43:163210 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013211 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313212
3213 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013214 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313215
bnc691fda62016-08-12 00:43:163216 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523217 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583218 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503219 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313220}
3221
[email protected]394816e92010-08-03 07:38:593222// Test the request-challenge-retry sequence for basic auth, over a connection
3223// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013224TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013225 HttpRequestInfo request;
3226 request.method = "GET";
bncce36dca22015-04-21 22:11:233227 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013228 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293229 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103230 request.traffic_annotation =
3231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013232
3233 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593234 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563235 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493236 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143237 RecordingBoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013238 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093239 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013240
3241 // Since we have proxy, should try to establish tunnel.
3242 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543243 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173244 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543245 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013246 };
3247
mmenkee71e15332015-10-07 16:39:543248 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013249 // connection.
3250 MockRead data_reads1[] = {
3251 // No credentials.
3252 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3253 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543254 };
ttuttle34f63b52015-03-05 04:33:013255
mmenkee71e15332015-10-07 16:39:543256 // Since the first connection couldn't be reused, need to establish another
3257 // once given credentials.
3258 MockWrite data_writes2[] = {
3259 // After calling trans->RestartWithAuth(), this is the request we should
3260 // be issuing -- the final header line contains the credentials.
3261 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173262 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543263 "Proxy-Connection: keep-alive\r\n"
3264 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3265
3266 MockWrite("GET / HTTP/1.1\r\n"
3267 "Host: www.example.org\r\n"
3268 "Connection: keep-alive\r\n\r\n"),
3269 };
3270
3271 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013272 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3273
3274 MockRead("HTTP/1.1 200 OK\r\n"),
3275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3276 MockRead("Content-Length: 5\r\n\r\n"),
3277 MockRead(SYNCHRONOUS, "hello"),
3278 };
3279
Ryan Sleevib8d7ea02018-05-07 20:01:013280 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013281 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013282 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543283 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013284 SSLSocketDataProvider ssl(ASYNC, OK);
3285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3286
3287 TestCompletionCallback callback1;
3288
bnc87dcefc2017-05-25 12:47:583289 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193290 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013291
3292 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013293 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013294
3295 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013296 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543297 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013298 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003299 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3300 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013301 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003302 entries, pos,
3303 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3304 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013305
3306 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523307 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013308 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523309 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013310 EXPECT_EQ(407, response->headers->response_code());
3311 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583312 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013313
3314 LoadTimingInfo load_timing_info;
3315 // CONNECT requests and responses are handled at the connect job level, so
3316 // the transaction does not yet have a connection.
3317 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3318
3319 TestCompletionCallback callback2;
3320
3321 rv =
3322 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013323 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013324
3325 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013326 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013327
3328 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523329 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013330
3331 EXPECT_TRUE(response->headers->IsKeepAlive());
3332 EXPECT_EQ(200, response->headers->response_code());
3333 EXPECT_EQ(5, response->headers->GetContentLength());
3334 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3335
Matt Menke96092e62019-10-18 04:09:333336 // Check that credentials were successfully cached, with the right target.
3337 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3338 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263339 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333340 ASSERT_TRUE(entry);
3341 ASSERT_EQ(kFoo, entry->credentials().username());
3342 ASSERT_EQ(kBar, entry->credentials().password());
3343
ttuttle34f63b52015-03-05 04:33:013344 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583345 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013346
3347 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3348 TestLoadTimingNotReusedWithPac(load_timing_info,
3349 CONNECT_TIMING_HAS_SSL_TIMES);
3350
3351 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113352 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle34f63b52015-03-05 04:33:013353}
3354
3355// Test the request-challenge-retry sequence for basic auth, over a connection
3356// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013357TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593358 HttpRequestInfo request;
3359 request.method = "GET";
bncce36dca22015-04-21 22:11:233360 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593361 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293362 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103363 request.traffic_annotation =
3364 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593365
[email protected]cb9bf6ca2011-01-28 13:15:273366 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593367 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563368 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493369 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143370 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073371 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093372 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273373
[email protected]394816e92010-08-03 07:38:593374 // Since we have proxy, should try to establish tunnel.
3375 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543376 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173377 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543378 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113379 };
3380
mmenkee71e15332015-10-07 16:39:543381 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083382 // connection.
3383 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543384 // No credentials.
3385 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3386 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3387 MockRead("Proxy-Connection: close\r\n\r\n"),
3388 };
mmenkee0b5c882015-08-26 20:29:113389
mmenkee71e15332015-10-07 16:39:543390 MockWrite data_writes2[] = {
3391 // After calling trans->RestartWithAuth(), this is the request we should
3392 // be issuing -- the final header line contains the credentials.
3393 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173394 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543395 "Proxy-Connection: keep-alive\r\n"
3396 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083397
mmenkee71e15332015-10-07 16:39:543398 MockWrite("GET / HTTP/1.1\r\n"
3399 "Host: www.example.org\r\n"
3400 "Connection: keep-alive\r\n\r\n"),
3401 };
3402
3403 MockRead data_reads2[] = {
3404 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3405
3406 MockRead("HTTP/1.1 200 OK\r\n"),
3407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3408 MockRead("Content-Length: 5\r\n\r\n"),
3409 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593410 };
3411
Ryan Sleevib8d7ea02018-05-07 20:01:013412 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073413 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013414 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543415 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063416 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593418
[email protected]49639fa2011-12-20 23:22:413419 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593420
bnc87dcefc2017-05-25 12:47:583421 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193422 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503423
[email protected]49639fa2011-12-20 23:22:413424 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013425 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593426
3427 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013428 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543429 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593430 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003431 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3432 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593433 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403434 entries, pos,
mikecirone8b85c432016-09-08 19:11:003435 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3436 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593437
3438 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523439 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013440 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523441 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593442 EXPECT_EQ(407, response->headers->response_code());
3443 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583444 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593445
[email protected]029c83b62013-01-24 05:28:203446 LoadTimingInfo load_timing_info;
3447 // CONNECT requests and responses are handled at the connect job level, so
3448 // the transaction does not yet have a connection.
3449 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3450
[email protected]49639fa2011-12-20 23:22:413451 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593452
[email protected]49639fa2011-12-20 23:22:413453 rv = trans->RestartWithAuth(
3454 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013455 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593456
3457 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013458 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593459
3460 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523461 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593462
3463 EXPECT_TRUE(response->headers->IsKeepAlive());
3464 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503465 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593466 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3467
3468 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583469 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503470
[email protected]029c83b62013-01-24 05:28:203471 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3472 TestLoadTimingNotReusedWithPac(load_timing_info,
3473 CONNECT_TIMING_HAS_SSL_TIMES);
3474
[email protected]0b0bf032010-09-21 18:08:503475 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113476 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]394816e92010-08-03 07:38:593477}
3478
[email protected]11203f012009-11-12 23:02:313479// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013480// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013481TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233482 // On the second pass, the body read of the auth challenge is synchronous, so
3483 // IsConnectedAndIdle returns false. The socket should still be drained and
3484 // reused. See http://crbug.com/544255.
3485 for (int i = 0; i < 2; ++i) {
3486 HttpRequestInfo request;
3487 request.method = "GET";
3488 request.url = GURL("https://www.example.org/");
3489 // Ensure that proxy authentication is attempted even
3490 // when the no authentication data flag is set.
3491 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103492 request.traffic_annotation =
3493 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013494
mmenked39192ee2015-12-09 00:57:233495 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593496 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563497 ConfiguredProxyResolutionService::CreateFixed(
3498 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143499 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233500 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013502
bnc691fda62016-08-12 00:43:163503 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013504
mmenked39192ee2015-12-09 00:57:233505 // Since we have proxy, should try to establish tunnel.
3506 MockWrite data_writes1[] = {
3507 MockWrite(ASYNC, 0,
3508 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3509 "Host: www.example.org:443\r\n"
3510 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013511
bnc691fda62016-08-12 00:43:163512 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233513 // be issuing -- the final header line contains the credentials.
3514 MockWrite(ASYNC, 3,
3515 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3516 "Host: www.example.org:443\r\n"
3517 "Proxy-Connection: keep-alive\r\n"
3518 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3519 };
ttuttle34f63b52015-03-05 04:33:013520
mmenked39192ee2015-12-09 00:57:233521 // The proxy responds to the connect with a 407, using a persistent
3522 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3523 MockRead data_reads1[] = {
3524 // No credentials.
3525 MockRead(ASYNC, 1,
3526 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3527 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3528 "Proxy-Connection: keep-alive\r\n"
3529 "Content-Length: 10\r\n\r\n"),
3530 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013531
mmenked39192ee2015-12-09 00:57:233532 // Wrong credentials (wrong password).
3533 MockRead(ASYNC, 4,
3534 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3535 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3536 "Proxy-Connection: keep-alive\r\n"
3537 "Content-Length: 10\r\n\r\n"),
3538 // No response body because the test stops reading here.
3539 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3540 };
ttuttle34f63b52015-03-05 04:33:013541
Ryan Sleevib8d7ea02018-05-07 20:01:013542 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233543 data1.set_busy_before_sync_reads(true);
3544 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013545
mmenked39192ee2015-12-09 00:57:233546 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013547
bnc691fda62016-08-12 00:43:163548 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013549 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013550
Eric Roman79cc7552019-07-19 02:17:543551 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233552 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003553 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3554 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233555 ExpectLogContainsSomewhere(
3556 entries, pos,
mikecirone8b85c432016-09-08 19:11:003557 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3558 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013559
bnc691fda62016-08-12 00:43:163560 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233561 ASSERT_TRUE(response);
3562 ASSERT_TRUE(response->headers);
3563 EXPECT_TRUE(response->headers->IsKeepAlive());
3564 EXPECT_EQ(407, response->headers->response_code());
3565 EXPECT_EQ(10, response->headers->GetContentLength());
3566 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583567 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013568
mmenked39192ee2015-12-09 00:57:233569 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013570
mmenked39192ee2015-12-09 00:57:233571 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163572 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3573 callback2.callback());
robpercival214763f2016-07-01 23:27:013574 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013575
bnc691fda62016-08-12 00:43:163576 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233577 ASSERT_TRUE(response);
3578 ASSERT_TRUE(response->headers);
3579 EXPECT_TRUE(response->headers->IsKeepAlive());
3580 EXPECT_EQ(407, response->headers->response_code());
3581 EXPECT_EQ(10, response->headers->GetContentLength());
3582 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583583 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013584
mmenked39192ee2015-12-09 00:57:233585 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3586 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113587 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233588 }
ttuttle34f63b52015-03-05 04:33:013589}
3590
3591// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3592// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013593TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233594 // On the second pass, the body read of the auth challenge is synchronous, so
3595 // IsConnectedAndIdle returns false. The socket should still be drained and
3596 // reused. See http://crbug.com/544255.
3597 for (int i = 0; i < 2; ++i) {
3598 HttpRequestInfo request;
3599 request.method = "GET";
3600 request.url = GURL("https://www.example.org/");
3601 // Ensure that proxy authentication is attempted even
3602 // when the no authentication data flag is set.
3603 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103604 request.traffic_annotation =
3605 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233606
3607 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593608 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563609 ConfiguredProxyResolutionService::CreateFixed(
3610 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143611 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233612 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093613 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233614
bnc691fda62016-08-12 00:43:163615 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233616
3617 // Since we have proxy, should try to establish tunnel.
3618 MockWrite data_writes1[] = {
3619 MockWrite(ASYNC, 0,
3620 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3621 "Host: www.example.org:443\r\n"
3622 "Proxy-Connection: keep-alive\r\n\r\n"),
3623
bnc691fda62016-08-12 00:43:163624 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233625 // be issuing -- the final header line contains the credentials.
3626 MockWrite(ASYNC, 3,
3627 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3628 "Host: www.example.org:443\r\n"
3629 "Proxy-Connection: keep-alive\r\n"
3630 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3631 };
3632
3633 // The proxy responds to the connect with a 407, using a persistent
3634 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3635 MockRead data_reads1[] = {
3636 // No credentials.
3637 MockRead(ASYNC, 1,
3638 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3639 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3640 "Content-Length: 10\r\n\r\n"),
3641 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3642
3643 // Wrong credentials (wrong password).
3644 MockRead(ASYNC, 4,
3645 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3646 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3647 "Content-Length: 10\r\n\r\n"),
3648 // No response body because the test stops reading here.
3649 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3650 };
3651
Ryan Sleevib8d7ea02018-05-07 20:01:013652 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233653 data1.set_busy_before_sync_reads(true);
3654 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3655
3656 TestCompletionCallback callback1;
3657
bnc691fda62016-08-12 00:43:163658 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013659 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233660
Eric Roman79cc7552019-07-19 02:17:543661 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233662 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003663 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3664 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233665 ExpectLogContainsSomewhere(
3666 entries, pos,
mikecirone8b85c432016-09-08 19:11:003667 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3668 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233669
bnc691fda62016-08-12 00:43:163670 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233671 ASSERT_TRUE(response);
3672 ASSERT_TRUE(response->headers);
3673 EXPECT_TRUE(response->headers->IsKeepAlive());
3674 EXPECT_EQ(407, response->headers->response_code());
3675 EXPECT_EQ(10, response->headers->GetContentLength());
3676 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583677 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503678 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233679
3680 TestCompletionCallback callback2;
3681
3682 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163683 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3684 callback2.callback());
robpercival214763f2016-07-01 23:27:013685 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233686
bnc691fda62016-08-12 00:43:163687 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233688 ASSERT_TRUE(response);
3689 ASSERT_TRUE(response->headers);
3690 EXPECT_TRUE(response->headers->IsKeepAlive());
3691 EXPECT_EQ(407, response->headers->response_code());
3692 EXPECT_EQ(10, response->headers->GetContentLength());
3693 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583694 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503695 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233696
3697 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3698 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113699 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233700 }
3701}
3702
3703// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3704// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3705// the case the server sends extra data on the original socket, so it can't be
3706// reused.
bncd16676a2016-07-20 16:23:013707TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273708 HttpRequestInfo request;
3709 request.method = "GET";
bncce36dca22015-04-21 22:11:233710 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273711 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293712 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103713 request.traffic_annotation =
3714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273715
[email protected]2d2697f92009-02-18 21:00:323716 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593717 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563718 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493719 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143720 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073721 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093722 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323723
[email protected]2d2697f92009-02-18 21:00:323724 // Since we have proxy, should try to establish tunnel.
3725 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233726 MockWrite(ASYNC, 0,
3727 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173728 "Host: www.example.org:443\r\n"
3729 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233730 };
[email protected]2d2697f92009-02-18 21:00:323731
mmenked39192ee2015-12-09 00:57:233732 // The proxy responds to the connect with a 407, using a persistent, but sends
3733 // extra data, so the socket cannot be reused.
3734 MockRead data_reads1[] = {
3735 // No credentials.
3736 MockRead(ASYNC, 1,
3737 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3738 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3739 "Content-Length: 10\r\n\r\n"),
3740 MockRead(SYNCHRONOUS, 2, "0123456789"),
3741 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3742 };
3743
3744 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233745 // After calling trans->RestartWithAuth(), this is the request we should
3746 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233747 MockWrite(ASYNC, 0,
3748 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173749 "Host: www.example.org:443\r\n"
3750 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233751 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3752
3753 MockWrite(ASYNC, 2,
3754 "GET / HTTP/1.1\r\n"
3755 "Host: www.example.org\r\n"
3756 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323757 };
3758
mmenked39192ee2015-12-09 00:57:233759 MockRead data_reads2[] = {
3760 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323761
mmenked39192ee2015-12-09 00:57:233762 MockRead(ASYNC, 3,
3763 "HTTP/1.1 200 OK\r\n"
3764 "Content-Type: text/html; charset=iso-8859-1\r\n"
3765 "Content-Length: 5\r\n\r\n"),
3766 // No response body because the test stops reading here.
3767 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323768 };
3769
Ryan Sleevib8d7ea02018-05-07 20:01:013770 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233771 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073772 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013773 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3775 SSLSocketDataProvider ssl(ASYNC, OK);
3776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323777
[email protected]49639fa2011-12-20 23:22:413778 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323779
bnc87dcefc2017-05-25 12:47:583780 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193781 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323782
mmenked39192ee2015-12-09 00:57:233783 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013784 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233785
Eric Roman79cc7552019-07-19 02:17:543786 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393787 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003788 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3789 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393790 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403791 entries, pos,
mikecirone8b85c432016-09-08 19:11:003792 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3793 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323794
[email protected]1c773ea12009-04-28 19:58:423795 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243796 ASSERT_TRUE(response);
3797 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323798 EXPECT_TRUE(response->headers->IsKeepAlive());
3799 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423800 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583801 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323802
mmenked39192ee2015-12-09 00:57:233803 LoadTimingInfo load_timing_info;
3804 // CONNECT requests and responses are handled at the connect job level, so
3805 // the transaction does not yet have a connection.
3806 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3807
[email protected]49639fa2011-12-20 23:22:413808 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323809
mmenked39192ee2015-12-09 00:57:233810 rv =
3811 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013812 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323813
[email protected]2d2697f92009-02-18 21:00:323814 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233815 EXPECT_EQ(200, response->headers->response_code());
3816 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423817 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133818
mmenked39192ee2015-12-09 00:57:233819 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583820 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233821
3822 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3823 TestLoadTimingNotReusedWithPac(load_timing_info,
3824 CONNECT_TIMING_HAS_SSL_TIMES);
3825
3826 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113827 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]2d2697f92009-02-18 21:00:323828}
3829
mmenkee71e15332015-10-07 16:39:543830// Test the case a proxy closes a socket while the challenge body is being
3831// drained.
bncd16676a2016-07-20 16:23:013832TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543833 HttpRequestInfo request;
3834 request.method = "GET";
3835 request.url = GURL("https://www.example.org/");
3836 // Ensure that proxy authentication is attempted even
3837 // when the no authentication data flag is set.
3838 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103839 request.traffic_annotation =
3840 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543841
3842 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:563843 session_deps_.proxy_resolution_service =
3844 ConfiguredProxyResolutionService::CreateFixed(
3845 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093846 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543847
bnc691fda62016-08-12 00:43:163848 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543849
3850 // Since we have proxy, should try to establish tunnel.
3851 MockWrite data_writes1[] = {
3852 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173853 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543854 "Proxy-Connection: keep-alive\r\n\r\n"),
3855 };
3856
3857 // The proxy responds to the connect with a 407, using a persistent
3858 // connection.
3859 MockRead data_reads1[] = {
3860 // No credentials.
3861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3862 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3863 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3864 // Server hands up in the middle of the body.
3865 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3866 };
3867
3868 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163869 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543870 // be issuing -- the final header line contains the credentials.
3871 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173872 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543873 "Proxy-Connection: keep-alive\r\n"
3874 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3875
3876 MockWrite("GET / HTTP/1.1\r\n"
3877 "Host: www.example.org\r\n"
3878 "Connection: keep-alive\r\n\r\n"),
3879 };
3880
3881 MockRead data_reads2[] = {
3882 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3883
3884 MockRead("HTTP/1.1 200 OK\r\n"),
3885 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3886 MockRead("Content-Length: 5\r\n\r\n"),
3887 MockRead(SYNCHRONOUS, "hello"),
3888 };
3889
Ryan Sleevib8d7ea02018-05-07 20:01:013890 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013892 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543893 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3894 SSLSocketDataProvider ssl(ASYNC, OK);
3895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3896
3897 TestCompletionCallback callback;
3898
tfarina42834112016-09-22 13:38:203899 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013900 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543901
bnc691fda62016-08-12 00:43:163902 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543903 ASSERT_TRUE(response);
3904 ASSERT_TRUE(response->headers);
3905 EXPECT_TRUE(response->headers->IsKeepAlive());
3906 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583907 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543908
bnc691fda62016-08-12 00:43:163909 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013910 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543911
bnc691fda62016-08-12 00:43:163912 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543913 ASSERT_TRUE(response);
3914 ASSERT_TRUE(response->headers);
3915 EXPECT_TRUE(response->headers->IsKeepAlive());
3916 EXPECT_EQ(200, response->headers->response_code());
3917 std::string body;
bnc691fda62016-08-12 00:43:163918 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543919 EXPECT_EQ("hello", body);
3920}
3921
[email protected]a8e9b162009-03-12 00:06:443922// Test that we don't read the response body when we fail to establish a tunnel,
3923// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013924TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273925 HttpRequestInfo request;
3926 request.method = "GET";
bncce36dca22015-04-21 22:11:233927 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103928 request.traffic_annotation =
3929 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273930
[email protected]a8e9b162009-03-12 00:06:443931 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:563932 session_deps_.proxy_resolution_service =
3933 ConfiguredProxyResolutionService::CreateFixed(
3934 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443935
danakj1fd259a02016-04-16 03:17:093936 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443937
bnc691fda62016-08-12 00:43:163938 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443939
[email protected]a8e9b162009-03-12 00:06:443940 // Since we have proxy, should try to establish tunnel.
3941 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173942 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3943 "Host: www.example.org:443\r\n"
3944 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443945 };
3946
3947 // The proxy responds to the connect with a 407.
3948 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243949 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3950 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3951 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233952 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243953 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443954 };
3955
Ryan Sleevib8d7ea02018-05-07 20:01:013956 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073957 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443958
[email protected]49639fa2011-12-20 23:22:413959 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443960
tfarina42834112016-09-22 13:38:203961 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443963
3964 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013965 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443966
bnc691fda62016-08-12 00:43:163967 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243968 ASSERT_TRUE(response);
3969 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443970 EXPECT_TRUE(response->headers->IsKeepAlive());
3971 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423972 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443973
3974 std::string response_data;
bnc691fda62016-08-12 00:43:163975 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013976 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183977
3978 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:113979 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]a8e9b162009-03-12 00:06:443980}
3981
Matt Menke96092e62019-10-18 04:09:333982// Test the no-tunnel HTTP auth case where proxy and server origins and realms
3983// are the same, but the user/passwords are different. Serves to verify
3984// credentials are correctly separated based on HttpAuth::Target.
3985TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
3986 HttpRequestInfo request;
3987 request.method = "GET";
3988 request.url = GURL("http://myproxy:70/");
3989 request.traffic_annotation =
3990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3991
3992 // Proxy matches request URL.
3993 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563994 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke96092e62019-10-18 04:09:333995 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143996 RecordingBoundTestNetLog log;
Matt Menke96092e62019-10-18 04:09:333997 session_deps_.net_log = log.bound().net_log();
3998 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3999
4000 MockWrite data_writes[] = {
4001 // Initial request gets a proxy auth challenge.
4002 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4003 "Host: myproxy:70\r\n"
4004 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264005 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334006 // challenge.
4007 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4008 "Host: myproxy:70\r\n"
4009 "Proxy-Connection: keep-alive\r\n"
4010 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264011 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334012 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4013 "Host: myproxy:70\r\n"
4014 "Proxy-Connection: keep-alive\r\n"
4015 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4016 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4017 // A second request should preemptively send the correct proxy and server
4018 // auth headers.
4019 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4020 "Host: myproxy:70\r\n"
4021 "Proxy-Connection: keep-alive\r\n"
4022 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4023 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4024 };
4025
4026 MockRead data_reads[] = {
4027 // Proxy auth challenge.
4028 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4029 "Proxy-Connection: keep-alive\r\n"
4030 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4031 "Content-Length: 0\r\n\r\n"),
4032 // Server auth challenge.
4033 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4034 "Proxy-Connection: keep-alive\r\n"
4035 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4036 "Content-Length: 0\r\n\r\n"),
4037 // Response.
4038 MockRead("HTTP/1.1 200 OK\r\n"
4039 "Proxy-Connection: keep-alive\r\n"
4040 "Content-Length: 5\r\n\r\n"
4041 "hello"),
4042 // Response to second request.
4043 MockRead("HTTP/1.1 200 OK\r\n"
4044 "Proxy-Connection: keep-alive\r\n"
4045 "Content-Length: 2\r\n\r\n"
4046 "hi"),
4047 };
4048
4049 StaticSocketDataProvider data(data_reads, data_writes);
4050 session_deps_.socket_factory->AddSocketDataProvider(&data);
4051
4052 TestCompletionCallback callback;
4053
4054 auto trans =
4055 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4056 int rv = trans->Start(&request, callback.callback(), log.bound());
4057 EXPECT_THAT(callback.GetResult(rv), IsOk());
4058 const HttpResponseInfo* response = trans->GetResponseInfo();
4059 ASSERT_TRUE(response);
4060 ASSERT_TRUE(response->headers);
4061 EXPECT_EQ(407, response->headers->response_code());
4062 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4063
4064 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4065 EXPECT_THAT(callback.GetResult(rv), IsOk());
4066 response = trans->GetResponseInfo();
4067 ASSERT_TRUE(response);
4068 EXPECT_EQ(401, response->headers->response_code());
4069 EXPECT_FALSE(response->auth_challenge->is_proxy);
4070 EXPECT_EQ("http://myproxy:70",
4071 response->auth_challenge->challenger.Serialize());
4072 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4073 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4074
4075 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4076 callback.callback());
4077 EXPECT_THAT(callback.GetResult(rv), IsOk());
4078 response = trans->GetResponseInfo();
4079 ASSERT_TRUE(response);
4080 EXPECT_EQ(200, response->headers->response_code());
4081 // The password prompt info should not be set.
4082 EXPECT_FALSE(response->auth_challenge.has_value());
4083
4084 std::string response_data;
4085 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4086 EXPECT_EQ("hello", response_data);
4087
4088 // Check that the credentials were cached correctly.
4089 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4090 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264091 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334092 ASSERT_TRUE(entry);
4093 ASSERT_EQ(kFoo, entry->credentials().username());
4094 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264095 entry = session->http_auth_cache()->Lookup(
4096 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4097 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334098 ASSERT_TRUE(entry);
4099 ASSERT_EQ(kFoo2, entry->credentials().username());
4100 ASSERT_EQ(kBar2, entry->credentials().password());
4101
4102 // Make another request, which should automatically send the correct proxy and
4103 // server auth credentials and get another response.
4104 trans =
4105 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4106 rv = trans->Start(&request, callback.callback(), log.bound());
4107 EXPECT_THAT(callback.GetResult(rv), IsOk());
4108 response = trans->GetResponseInfo();
4109 ASSERT_TRUE(response);
4110 EXPECT_EQ(200, response->headers->response_code());
4111 // The password prompt info should not be set.
4112 EXPECT_FALSE(response->auth_challenge.has_value());
4113
4114 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4115 EXPECT_EQ("hi", response_data);
4116
4117 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114118 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menke96092e62019-10-18 04:09:334119}
4120
Matt Menkebe090422019-10-18 20:25:264121// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4122// are the same, but the user/passwords are different, and with different
4123// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4124// and auth challenges, sends another request with another NIK, expecting only
4125// the proxy credentials to be cached, and thus sees only a server auth
4126// challenge. Then sends a request with the original NIK, expecting cached proxy
4127// and auth credentials that match the ones used in the first request.
4128//
4129// Serves to verify credentials are correctly separated based on
4130// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4131// affects server credentials, not proxy credentials.
4132TEST_F(HttpNetworkTransactionTest,
4133 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
4134 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4135 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4136 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4137 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4138
4139 // This test would need to use a single socket without this option enabled.
4140 // Best to use this option when it would affect a test, as it will eventually
4141 // become the default behavior.
4142 base::test::ScopedFeatureList feature_list;
4143 feature_list.InitAndEnableFeature(
4144 features::kPartitionConnectionsByNetworkIsolationKey);
4145
4146 // Proxy matches request URL.
4147 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564148 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264149 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144150 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264151 session_deps_.net_log = log.bound().net_log();
4152 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4153 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4154
4155 MockWrite data_writes[] = {
4156 // Initial request gets a proxy auth challenge.
4157 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4158 "Host: myproxy:70\r\n"
4159 "Proxy-Connection: keep-alive\r\n\r\n"),
4160 // Retry with proxy auth credentials, which will result in a server auth
4161 // challenge.
4162 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4163 "Host: myproxy:70\r\n"
4164 "Proxy-Connection: keep-alive\r\n"
4165 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4166 // Retry with proxy and server auth credentials, which gets a response.
4167 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4168 "Host: myproxy:70\r\n"
4169 "Proxy-Connection: keep-alive\r\n"
4170 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4171 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4172 // Another request to the same server and using the same NIK should
4173 // preemptively send the correct cached proxy and server
4174 // auth headers.
4175 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4176 "Host: myproxy:70\r\n"
4177 "Proxy-Connection: keep-alive\r\n"
4178 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4179 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4180 };
4181
4182 MockRead data_reads[] = {
4183 // Proxy auth challenge.
4184 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4185 "Proxy-Connection: keep-alive\r\n"
4186 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4187 "Content-Length: 0\r\n\r\n"),
4188 // Server auth challenge.
4189 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4190 "Proxy-Connection: keep-alive\r\n"
4191 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4192 "Content-Length: 0\r\n\r\n"),
4193 // Response.
4194 MockRead("HTTP/1.1 200 OK\r\n"
4195 "Proxy-Connection: keep-alive\r\n"
4196 "Content-Length: 5\r\n\r\n"
4197 "hello"),
4198 // Response to second request.
4199 MockRead("HTTP/1.1 200 OK\r\n"
4200 "Proxy-Connection: keep-alive\r\n"
4201 "Content-Length: 2\r\n\r\n"
4202 "hi"),
4203 };
4204
4205 StaticSocketDataProvider data(data_reads, data_writes);
4206 session_deps_.socket_factory->AddSocketDataProvider(&data);
4207
4208 MockWrite data_writes2[] = {
4209 // Initial request using a different NetworkIsolationKey includes the
4210 // cached proxy credentials, but not server credentials.
4211 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4212 "Host: myproxy:70\r\n"
4213 "Proxy-Connection: keep-alive\r\n"
4214 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4215 // Retry with proxy and new server auth credentials, which gets a
4216 // response.
4217 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4218 "Host: myproxy:70\r\n"
4219 "Proxy-Connection: keep-alive\r\n"
4220 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4221 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4222 };
4223
4224 MockRead data_reads2[] = {
4225 // Server auth challenge.
4226 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4227 "Proxy-Connection: keep-alive\r\n"
4228 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4229 "Content-Length: 0\r\n\r\n"),
4230 // Response.
4231 MockRead("HTTP/1.1 200 OK\r\n"
4232 "Proxy-Connection: keep-alive\r\n"
4233 "Content-Length: 9\r\n\r\n"
4234 "greetings"),
4235 };
4236
4237 StaticSocketDataProvider data2(data_reads2, data_writes2);
4238 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4239
4240 TestCompletionCallback callback;
4241
4242 HttpRequestInfo request;
4243 request.method = "GET";
4244 request.url = GURL("http://myproxy:70/");
4245 request.traffic_annotation =
4246 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4247 request.network_isolation_key = kNetworkIsolationKey1;
4248
4249 auto trans =
4250 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4251 int rv = trans->Start(&request, callback.callback(), log.bound());
4252 EXPECT_THAT(callback.GetResult(rv), IsOk());
4253 const HttpResponseInfo* response = trans->GetResponseInfo();
4254 ASSERT_TRUE(response);
4255 ASSERT_TRUE(response->headers);
4256 EXPECT_EQ(407, response->headers->response_code());
4257 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4258
4259 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4260 EXPECT_THAT(callback.GetResult(rv), IsOk());
4261 response = trans->GetResponseInfo();
4262 ASSERT_TRUE(response);
4263 EXPECT_EQ(401, response->headers->response_code());
4264 EXPECT_FALSE(response->auth_challenge->is_proxy);
4265 EXPECT_EQ("http://myproxy:70",
4266 response->auth_challenge->challenger.Serialize());
4267 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4268 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4269
4270 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4271 callback.callback());
4272 EXPECT_THAT(callback.GetResult(rv), IsOk());
4273 response = trans->GetResponseInfo();
4274 ASSERT_TRUE(response);
4275 EXPECT_EQ(200, response->headers->response_code());
4276 // The password prompt info should not be set.
4277 EXPECT_FALSE(response->auth_challenge.has_value());
4278 std::string response_data;
4279 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4280 EXPECT_EQ("hello", response_data);
4281
4282 // Check that the proxy credentials were cached correctly. The should be
4283 // accessible with any NetworkIsolationKey.
4284 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4285 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4286 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4287 ASSERT_TRUE(entry);
4288 ASSERT_EQ(kFoo, entry->credentials().username());
4289 ASSERT_EQ(kBar, entry->credentials().password());
4290 EXPECT_EQ(entry,
4291 session->http_auth_cache()->Lookup(
4292 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4293 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4294
4295 // Check that the server credentials were cached correctly. The should be
4296 // accessible with only kNetworkIsolationKey1.
4297 entry = session->http_auth_cache()->Lookup(
4298 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4299 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4300 ASSERT_TRUE(entry);
4301 ASSERT_EQ(kFoo2, entry->credentials().username());
4302 ASSERT_EQ(kBar2, entry->credentials().password());
4303 // Looking up the server entry with another NetworkIsolationKey should fail.
4304 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4305 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4306 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4307
4308 // Make another request with a different NetworkIsolationKey. It should use
4309 // another socket, reuse the cached proxy credentials, but result in a server
4310 // auth challenge.
4311 request.network_isolation_key = kNetworkIsolationKey2;
4312 trans =
4313 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4314 rv = trans->Start(&request, callback.callback(), log.bound());
4315 EXPECT_THAT(callback.GetResult(rv), IsOk());
4316 response = trans->GetResponseInfo();
4317 ASSERT_TRUE(response);
4318 EXPECT_EQ(401, response->headers->response_code());
4319 EXPECT_FALSE(response->auth_challenge->is_proxy);
4320 EXPECT_EQ("http://myproxy:70",
4321 response->auth_challenge->challenger.Serialize());
4322 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4323 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4324
4325 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4326 callback.callback());
4327 EXPECT_THAT(callback.GetResult(rv), IsOk());
4328 response = trans->GetResponseInfo();
4329 ASSERT_TRUE(response);
4330 EXPECT_EQ(200, response->headers->response_code());
4331 // The password prompt info should not be set.
4332 EXPECT_FALSE(response->auth_challenge.has_value());
4333 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4334 EXPECT_EQ("greetings", response_data);
4335
4336 // Check that the proxy credentials are still cached.
4337 entry = session->http_auth_cache()->Lookup(
4338 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4339 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4340 ASSERT_TRUE(entry);
4341 ASSERT_EQ(kFoo, entry->credentials().username());
4342 ASSERT_EQ(kBar, entry->credentials().password());
4343 EXPECT_EQ(entry,
4344 session->http_auth_cache()->Lookup(
4345 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4346 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4347
4348 // Check that the correct server credentials are cached for each
4349 // NetworkIsolationKey.
4350 entry = session->http_auth_cache()->Lookup(
4351 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4352 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4353 ASSERT_TRUE(entry);
4354 ASSERT_EQ(kFoo2, entry->credentials().username());
4355 ASSERT_EQ(kBar2, entry->credentials().password());
4356 entry = session->http_auth_cache()->Lookup(
4357 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4358 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4359 ASSERT_TRUE(entry);
4360 ASSERT_EQ(kFoo3, entry->credentials().username());
4361 ASSERT_EQ(kBar3, entry->credentials().password());
4362
4363 // Make a request with the original NetworkIsolationKey. It should reuse the
4364 // first socket, and the proxy credentials sent on the first socket.
4365 request.network_isolation_key = kNetworkIsolationKey1;
4366 trans =
4367 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4368 rv = trans->Start(&request, callback.callback(), log.bound());
4369 EXPECT_THAT(callback.GetResult(rv), IsOk());
4370 response = trans->GetResponseInfo();
4371 ASSERT_TRUE(response);
4372 EXPECT_EQ(200, response->headers->response_code());
4373 // The password prompt info should not be set.
4374 EXPECT_FALSE(response->auth_challenge.has_value());
4375 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4376 EXPECT_EQ("hi", response_data);
4377
4378 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114379 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264380}
4381
4382// Much like the test above, but uses tunnelled connections.
4383TEST_F(HttpNetworkTransactionTest,
4384 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
4385 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4386 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4387 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4388 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4389
4390 // This test would need to use a single socket without this option enabled.
4391 // Best to use this option when it would affect a test, as it will eventually
4392 // become the default behavior.
4393 base::test::ScopedFeatureList feature_list;
4394 feature_list.InitAndEnableFeature(
4395 features::kPartitionConnectionsByNetworkIsolationKey);
4396
4397 // Proxy matches request URL.
4398 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564399 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264400 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144401 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264402 session_deps_.net_log = log.bound().net_log();
4403 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4404 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4405
4406 MockWrite data_writes[] = {
4407 // Initial tunnel request gets a proxy auth challenge.
4408 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4409 "Host: myproxy:70\r\n"
4410 "Proxy-Connection: keep-alive\r\n\r\n"),
4411 // Retry with proxy auth credentials, which will result in establishing a
4412 // tunnel.
4413 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4414 "Host: myproxy:70\r\n"
4415 "Proxy-Connection: keep-alive\r\n"
4416 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4417 // Request over the tunnel, which gets a server auth challenge.
4418 MockWrite("GET / HTTP/1.1\r\n"
4419 "Host: myproxy:70\r\n"
4420 "Connection: keep-alive\r\n\r\n"),
4421 // Retry with server auth credentials, which gets a response.
4422 MockWrite("GET / HTTP/1.1\r\n"
4423 "Host: myproxy:70\r\n"
4424 "Connection: keep-alive\r\n"
4425 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4426 // Another request to the same server and using the same NIK should
4427 // preemptively send the correct cached server
4428 // auth header. Since a tunnel was already established, the proxy headers
4429 // won't be sent again except when establishing another tunnel.
4430 MockWrite("GET / HTTP/1.1\r\n"
4431 "Host: myproxy:70\r\n"
4432 "Connection: keep-alive\r\n"
4433 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4434 };
4435
4436 MockRead data_reads[] = {
4437 // Proxy auth challenge.
4438 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4439 "Proxy-Connection: keep-alive\r\n"
4440 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4441 "Content-Length: 0\r\n\r\n"),
4442 // Tunnel success
4443 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4444 // Server auth challenge.
4445 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4446 "Connection: keep-alive\r\n"
4447 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4448 "Content-Length: 0\r\n\r\n"),
4449 // Response.
4450 MockRead("HTTP/1.1 200 OK\r\n"
4451 "Connection: keep-alive\r\n"
4452 "Content-Length: 5\r\n\r\n"
4453 "hello"),
4454 // Response to second request.
4455 MockRead("HTTP/1.1 200 OK\r\n"
4456 "Connection: keep-alive\r\n"
4457 "Content-Length: 2\r\n\r\n"
4458 "hi"),
4459 };
4460
4461 StaticSocketDataProvider data(data_reads, data_writes);
4462 session_deps_.socket_factory->AddSocketDataProvider(&data);
4463 // One for the proxy connection, one of the server connection.
4464 SSLSocketDataProvider ssl(ASYNC, OK);
4465 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4466 SSLSocketDataProvider ssl2(ASYNC, OK);
4467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4468
4469 MockWrite data_writes2[] = {
4470 // Initial request using a different NetworkIsolationKey includes the
4471 // cached proxy credentials when establishing a tunnel.
4472 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4473 "Host: myproxy:70\r\n"
4474 "Proxy-Connection: keep-alive\r\n"
4475 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4476 // Request over the tunnel, which gets a server auth challenge. Cached
4477 // credentials cannot be used, since the NIK is different.
4478 MockWrite("GET / HTTP/1.1\r\n"
4479 "Host: myproxy:70\r\n"
4480 "Connection: keep-alive\r\n\r\n"),
4481 // Retry with server auth credentials, which gets a response.
4482 MockWrite("GET / HTTP/1.1\r\n"
4483 "Host: myproxy:70\r\n"
4484 "Connection: keep-alive\r\n"
4485 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4486 };
4487
4488 MockRead data_reads2[] = {
4489 // Tunnel success
4490 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4491 // Server auth challenge.
4492 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4493 "Connection: keep-alive\r\n"
4494 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4495 "Content-Length: 0\r\n\r\n"),
4496 // Response.
4497 MockRead("HTTP/1.1 200 OK\r\n"
4498 "Connection: keep-alive\r\n"
4499 "Content-Length: 9\r\n\r\n"
4500 "greetings"),
4501 };
4502
4503 StaticSocketDataProvider data2(data_reads2, data_writes2);
4504 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4505 // One for the proxy connection, one of the server connection.
4506 SSLSocketDataProvider ssl3(ASYNC, OK);
4507 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4508 SSLSocketDataProvider ssl4(ASYNC, OK);
4509 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4510
4511 TestCompletionCallback callback;
4512
4513 HttpRequestInfo request;
4514 request.method = "GET";
4515 request.url = GURL("https://myproxy:70/");
4516 request.traffic_annotation =
4517 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4518 request.network_isolation_key = kNetworkIsolationKey1;
4519
4520 auto trans =
4521 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4522 int rv = trans->Start(&request, callback.callback(), log.bound());
4523 EXPECT_THAT(callback.GetResult(rv), IsOk());
4524 const HttpResponseInfo* response = trans->GetResponseInfo();
4525 ASSERT_TRUE(response);
4526 ASSERT_TRUE(response->headers);
4527 EXPECT_EQ(407, response->headers->response_code());
4528 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4529
4530 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4531 EXPECT_THAT(callback.GetResult(rv), IsOk());
4532 response = trans->GetResponseInfo();
4533 ASSERT_TRUE(response);
4534 EXPECT_EQ(401, response->headers->response_code());
4535 EXPECT_FALSE(response->auth_challenge->is_proxy);
4536 EXPECT_EQ("https://myproxy:70",
4537 response->auth_challenge->challenger.Serialize());
4538 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4539 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4540
4541 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4542 callback.callback());
4543 EXPECT_THAT(callback.GetResult(rv), IsOk());
4544 response = trans->GetResponseInfo();
4545 ASSERT_TRUE(response);
4546 EXPECT_EQ(200, response->headers->response_code());
4547 // The password prompt info should not be set.
4548 EXPECT_FALSE(response->auth_challenge.has_value());
4549 std::string response_data;
4550 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4551 EXPECT_EQ("hello", response_data);
4552
4553 // Check that the proxy credentials were cached correctly. The should be
4554 // accessible with any NetworkIsolationKey.
4555 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4556 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4557 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4558 ASSERT_TRUE(entry);
4559 ASSERT_EQ(kFoo, entry->credentials().username());
4560 ASSERT_EQ(kBar, entry->credentials().password());
4561 EXPECT_EQ(entry,
4562 session->http_auth_cache()->Lookup(
4563 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4564 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4565
4566 // Check that the server credentials were cached correctly. The should be
4567 // accessible with only kNetworkIsolationKey1.
4568 entry = session->http_auth_cache()->Lookup(
4569 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4570 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4571 ASSERT_TRUE(entry);
4572 ASSERT_EQ(kFoo2, entry->credentials().username());
4573 ASSERT_EQ(kBar2, entry->credentials().password());
4574 // Looking up the server entry with another NetworkIsolationKey should fail.
4575 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4576 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4577 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4578
4579 // Make another request with a different NetworkIsolationKey. It should use
4580 // another socket, reuse the cached proxy credentials, but result in a server
4581 // auth challenge.
4582 request.network_isolation_key = kNetworkIsolationKey2;
4583 trans =
4584 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4585 rv = trans->Start(&request, callback.callback(), log.bound());
4586 EXPECT_THAT(callback.GetResult(rv), IsOk());
4587 response = trans->GetResponseInfo();
4588 ASSERT_TRUE(response);
4589 EXPECT_EQ(401, response->headers->response_code());
4590 EXPECT_FALSE(response->auth_challenge->is_proxy);
4591 EXPECT_EQ("https://myproxy:70",
4592 response->auth_challenge->challenger.Serialize());
4593 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4594 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4595
4596 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4597 callback.callback());
4598 EXPECT_THAT(callback.GetResult(rv), IsOk());
4599 response = trans->GetResponseInfo();
4600 ASSERT_TRUE(response);
4601 EXPECT_EQ(200, response->headers->response_code());
4602 // The password prompt info should not be set.
4603 EXPECT_FALSE(response->auth_challenge.has_value());
4604 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4605 EXPECT_EQ("greetings", response_data);
4606
4607 // Check that the proxy credentials are still cached.
4608 entry = session->http_auth_cache()->Lookup(
4609 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4610 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4611 ASSERT_TRUE(entry);
4612 ASSERT_EQ(kFoo, entry->credentials().username());
4613 ASSERT_EQ(kBar, entry->credentials().password());
4614 EXPECT_EQ(entry,
4615 session->http_auth_cache()->Lookup(
4616 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4617 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4618
4619 // Check that the correct server credentials are cached for each
4620 // NetworkIsolationKey.
4621 entry = session->http_auth_cache()->Lookup(
4622 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4623 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4624 ASSERT_TRUE(entry);
4625 ASSERT_EQ(kFoo2, entry->credentials().username());
4626 ASSERT_EQ(kBar2, entry->credentials().password());
4627 entry = session->http_auth_cache()->Lookup(
4628 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4629 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4630 ASSERT_TRUE(entry);
4631 ASSERT_EQ(kFoo3, entry->credentials().username());
4632 ASSERT_EQ(kBar3, entry->credentials().password());
4633
4634 // Make a request with the original NetworkIsolationKey. It should reuse the
4635 // first socket, and the proxy credentials sent on the first socket.
4636 request.network_isolation_key = kNetworkIsolationKey1;
4637 trans =
4638 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4639 rv = trans->Start(&request, callback.callback(), log.bound());
4640 EXPECT_THAT(callback.GetResult(rv), IsOk());
4641 response = trans->GetResponseInfo();
4642 ASSERT_TRUE(response);
4643 EXPECT_EQ(200, response->headers->response_code());
4644 // The password prompt info should not be set.
4645 EXPECT_FALSE(response->auth_challenge.has_value());
4646 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4647 EXPECT_EQ("hi", response_data);
4648
4649 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114650 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264651}
4652
ttuttle7933c112015-01-06 00:55:244653// Test that we don't pass extraneous headers from the proxy's response to the
4654// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014655TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244656 HttpRequestInfo request;
4657 request.method = "GET";
bncce36dca22015-04-21 22:11:234658 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104659 request.traffic_annotation =
4660 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244661
4662 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564663 session_deps_.proxy_resolution_service =
4664 ConfiguredProxyResolutionService::CreateFixed(
4665 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244666
danakj1fd259a02016-04-16 03:17:094667 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244668
bnc691fda62016-08-12 00:43:164669 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244670
4671 // Since we have proxy, should try to establish tunnel.
4672 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174673 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4674 "Host: www.example.org:443\r\n"
4675 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244676 };
4677
4678 // The proxy responds to the connect with a 407.
4679 MockRead data_reads[] = {
4680 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4681 MockRead("X-Foo: bar\r\n"),
4682 MockRead("Set-Cookie: foo=bar\r\n"),
4683 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4684 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234685 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244686 };
4687
Ryan Sleevib8d7ea02018-05-07 20:01:014688 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244689 session_deps_.socket_factory->AddSocketDataProvider(&data);
4690
4691 TestCompletionCallback callback;
4692
tfarina42834112016-09-22 13:38:204693 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244695
4696 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014697 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244698
bnc691fda62016-08-12 00:43:164699 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244700 ASSERT_TRUE(response);
4701 ASSERT_TRUE(response->headers);
4702 EXPECT_TRUE(response->headers->IsKeepAlive());
4703 EXPECT_EQ(407, response->headers->response_code());
4704 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4705 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4706 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4707
4708 std::string response_data;
bnc691fda62016-08-12 00:43:164709 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014710 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244711
4712 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114713 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle7933c112015-01-06 00:55:244714}
4715
[email protected]8fdbcd22010-05-05 02:54:524716// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4717// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014718TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524719 HttpRequestInfo request;
4720 request.method = "GET";
bncce36dca22015-04-21 22:11:234721 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104722 request.traffic_annotation =
4723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524724
[email protected]cb9bf6ca2011-01-28 13:15:274725 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164727 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274728
[email protected]8fdbcd22010-05-05 02:54:524729 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234730 MockWrite(
4731 "GET / HTTP/1.1\r\n"
4732 "Host: www.example.org\r\n"
4733 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524734 };
4735
4736 MockRead data_reads1[] = {
4737 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4738 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4739 // Large content-length -- won't matter, as connection will be reset.
4740 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064741 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524742 };
4743
Ryan Sleevib8d7ea02018-05-07 20:01:014744 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074745 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524746
[email protected]49639fa2011-12-20 23:22:414747 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524748
tfarina42834112016-09-22 13:38:204749 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014750 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524751
4752 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014753 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524754}
4755
[email protected]7a67a8152010-11-05 18:31:104756// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4757// through a non-authenticating proxy. The request should fail with
4758// ERR_UNEXPECTED_PROXY_AUTH.
4759// Note that it is impossible to detect if an HTTP server returns a 407 through
4760// a non-authenticating proxy - there is nothing to indicate whether the
4761// response came from the proxy or the server, so it is treated as if the proxy
4762// issued the challenge.
bncd16676a2016-07-20 16:23:014763TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274764 HttpRequestInfo request;
4765 request.method = "GET";
bncce36dca22015-04-21 22:11:234766 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104767 request.traffic_annotation =
4768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274769
Nicolas Arciniegad2013f92020-02-07 23:00:564770 session_deps_.proxy_resolution_service =
4771 ConfiguredProxyResolutionService::CreateFixed(
4772 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144773 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074774 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104776
[email protected]7a67a8152010-11-05 18:31:104777 // Since we have proxy, should try to establish tunnel.
4778 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174779 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4780 "Host: www.example.org:443\r\n"
4781 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104782
rsleevidb16bb02015-11-12 23:47:174783 MockWrite("GET / HTTP/1.1\r\n"
4784 "Host: www.example.org\r\n"
4785 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104786 };
4787
4788 MockRead data_reads1[] = {
4789 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4790
4791 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4792 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4793 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064794 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104795 };
4796
Ryan Sleevib8d7ea02018-05-07 20:01:014797 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074798 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064799 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104801
[email protected]49639fa2011-12-20 23:22:414802 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104803
bnc691fda62016-08-12 00:43:164804 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104805
bnc691fda62016-08-12 00:43:164806 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014807 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104808
4809 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014810 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544811 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104812 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004813 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4814 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104815 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404816 entries, pos,
mikecirone8b85c432016-09-08 19:11:004817 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4818 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104819}
[email protected]2df19bb2010-08-25 20:13:464820
mmenke2a1781d2015-10-07 19:25:334821// Test a proxy auth scheme that allows default credentials and a proxy server
4822// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014823TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334824 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4825 HttpRequestInfo request;
4826 request.method = "GET";
4827 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104828 request.traffic_annotation =
4829 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334830
4831 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594832 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564833 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:494834 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334835
Jeremy Roman0579ed62017-08-29 15:56:194836 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334837 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194838 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334839 mock_handler->set_allows_default_credentials(true);
4840 auth_handler_factory->AddMockHandler(mock_handler.release(),
4841 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484842 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334843
4844 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:584845 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:094846 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334847
4848 // Since we have proxy, should try to establish tunnel.
4849 MockWrite data_writes1[] = {
4850 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174851 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334852 "Proxy-Connection: keep-alive\r\n\r\n"),
4853 };
4854
4855 // The proxy responds to the connect with a 407, using a non-persistent
4856 // connection.
4857 MockRead data_reads1[] = {
4858 // No credentials.
4859 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4860 MockRead("Proxy-Authenticate: Mock\r\n"),
4861 MockRead("Proxy-Connection: close\r\n\r\n"),
4862 };
4863
4864 // Since the first connection couldn't be reused, need to establish another
4865 // once given credentials.
4866 MockWrite data_writes2[] = {
4867 // After calling trans->RestartWithAuth(), this is the request we should
4868 // be issuing -- the final header line contains the credentials.
4869 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174870 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334871 "Proxy-Connection: keep-alive\r\n"
4872 "Proxy-Authorization: auth_token\r\n\r\n"),
4873
4874 MockWrite("GET / HTTP/1.1\r\n"
4875 "Host: www.example.org\r\n"
4876 "Connection: keep-alive\r\n\r\n"),
4877 };
4878
4879 MockRead data_reads2[] = {
4880 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4881
4882 MockRead("HTTP/1.1 200 OK\r\n"),
4883 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4884 MockRead("Content-Length: 5\r\n\r\n"),
4885 MockRead(SYNCHRONOUS, "hello"),
4886 };
4887
Ryan Sleevib8d7ea02018-05-07 20:01:014888 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334889 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014890 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334891 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4892 SSLSocketDataProvider ssl(ASYNC, OK);
4893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4894
bnc87dcefc2017-05-25 12:47:584895 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194896 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334897
4898 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204899 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014900 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334901
4902 const HttpResponseInfo* response = trans->GetResponseInfo();
4903 ASSERT_TRUE(response);
4904 ASSERT_TRUE(response->headers);
4905 EXPECT_FALSE(response->headers->IsKeepAlive());
4906 EXPECT_EQ(407, response->headers->response_code());
4907 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4908 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584909 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334910
4911 LoadTimingInfo load_timing_info;
4912 // CONNECT requests and responses are handled at the connect job level, so
4913 // the transaction does not yet have a connection.
4914 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4915
4916 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014917 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334918 response = trans->GetResponseInfo();
4919 ASSERT_TRUE(response);
4920 ASSERT_TRUE(response->headers);
4921 EXPECT_TRUE(response->headers->IsKeepAlive());
4922 EXPECT_EQ(200, response->headers->response_code());
4923 EXPECT_EQ(5, response->headers->GetContentLength());
4924 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4925
4926 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584927 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334928
4929 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4930 TestLoadTimingNotReusedWithPac(load_timing_info,
4931 CONNECT_TIMING_HAS_SSL_TIMES);
4932
4933 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114934 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:334935}
4936
4937// Test a proxy auth scheme that allows default credentials and a proxy server
4938// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014939TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334940 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4941 HttpRequestInfo request;
4942 request.method = "GET";
4943 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104944 request.traffic_annotation =
4945 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334946
4947 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594948 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564949 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:494950 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334951
Jeremy Roman0579ed62017-08-29 15:56:194952 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334953 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194954 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334955 mock_handler->set_allows_default_credentials(true);
4956 auth_handler_factory->AddMockHandler(mock_handler.release(),
4957 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484958 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334959
4960 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:584961 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:094962 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334963
4964 // Should try to establish tunnel.
4965 MockWrite data_writes1[] = {
4966 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174967 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334968 "Proxy-Connection: keep-alive\r\n\r\n"),
4969
4970 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174971 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334972 "Proxy-Connection: keep-alive\r\n"
4973 "Proxy-Authorization: auth_token\r\n\r\n"),
4974 };
4975
4976 // The proxy responds to the connect with a 407, using a non-persistent
4977 // connection.
4978 MockRead data_reads1[] = {
4979 // No credentials.
4980 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4981 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4982 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4983 };
4984
4985 // Since the first connection was closed, need to establish another once given
4986 // credentials.
4987 MockWrite data_writes2[] = {
4988 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174989 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334990 "Proxy-Connection: keep-alive\r\n"
4991 "Proxy-Authorization: auth_token\r\n\r\n"),
4992
4993 MockWrite("GET / HTTP/1.1\r\n"
4994 "Host: www.example.org\r\n"
4995 "Connection: keep-alive\r\n\r\n"),
4996 };
4997
4998 MockRead data_reads2[] = {
4999 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5000
5001 MockRead("HTTP/1.1 200 OK\r\n"),
5002 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5003 MockRead("Content-Length: 5\r\n\r\n"),
5004 MockRead(SYNCHRONOUS, "hello"),
5005 };
5006
Ryan Sleevib8d7ea02018-05-07 20:01:015007 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335008 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015009 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335010 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5011 SSLSocketDataProvider ssl(ASYNC, OK);
5012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5013
bnc87dcefc2017-05-25 12:47:585014 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195015 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335016
5017 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205018 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015019 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335020
5021 const HttpResponseInfo* response = trans->GetResponseInfo();
5022 ASSERT_TRUE(response);
5023 ASSERT_TRUE(response->headers);
5024 EXPECT_TRUE(response->headers->IsKeepAlive());
5025 EXPECT_EQ(407, response->headers->response_code());
5026 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5027 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585028 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335029
5030 LoadTimingInfo load_timing_info;
5031 // CONNECT requests and responses are handled at the connect job level, so
5032 // the transaction does not yet have a connection.
5033 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5034
5035 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015036 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335037
5038 response = trans->GetResponseInfo();
5039 ASSERT_TRUE(response);
5040 ASSERT_TRUE(response->headers);
5041 EXPECT_TRUE(response->headers->IsKeepAlive());
5042 EXPECT_EQ(200, response->headers->response_code());
5043 EXPECT_EQ(5, response->headers->GetContentLength());
5044 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5045
5046 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585047 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335048
5049 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5050 TestLoadTimingNotReusedWithPac(load_timing_info,
5051 CONNECT_TIMING_HAS_SSL_TIMES);
5052
5053 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115054 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335055}
5056
5057// Test a proxy auth scheme that allows default credentials and a proxy server
5058// that hangs up when credentials are initially sent, and hangs up again when
5059// they are retried.
bncd16676a2016-07-20 16:23:015060TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335061 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5062 HttpRequestInfo request;
5063 request.method = "GET";
5064 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105065 request.traffic_annotation =
5066 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335067
5068 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595069 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565070 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495071 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335072
Jeremy Roman0579ed62017-08-29 15:56:195073 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335074 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195075 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335076 mock_handler->set_allows_default_credentials(true);
5077 auth_handler_factory->AddMockHandler(mock_handler.release(),
5078 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485079 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335080
5081 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585082 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095083 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335084
5085 // Should try to establish tunnel.
5086 MockWrite data_writes1[] = {
5087 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175088 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335089 "Proxy-Connection: keep-alive\r\n\r\n"),
5090
5091 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175092 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335093 "Proxy-Connection: keep-alive\r\n"
5094 "Proxy-Authorization: auth_token\r\n\r\n"),
5095 };
5096
5097 // The proxy responds to the connect with a 407, and then hangs up after the
5098 // second request is sent.
5099 MockRead data_reads1[] = {
5100 // No credentials.
5101 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5102 MockRead("Content-Length: 0\r\n"),
5103 MockRead("Proxy-Connection: keep-alive\r\n"),
5104 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5105 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5106 };
5107
5108 // HttpNetworkTransaction sees a reused connection that was closed with
5109 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5110 // request.
5111 MockWrite data_writes2[] = {
5112 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175113 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335114 "Proxy-Connection: keep-alive\r\n\r\n"),
5115 };
5116
5117 // The proxy, having had more than enough of us, just hangs up.
5118 MockRead data_reads2[] = {
5119 // No credentials.
5120 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5121 };
5122
Ryan Sleevib8d7ea02018-05-07 20:01:015123 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015125 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335126 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5127
bnc87dcefc2017-05-25 12:47:585128 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195129 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335130
5131 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205132 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015133 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335134
5135 const HttpResponseInfo* response = trans->GetResponseInfo();
5136 ASSERT_TRUE(response);
5137 ASSERT_TRUE(response->headers);
5138 EXPECT_TRUE(response->headers->IsKeepAlive());
5139 EXPECT_EQ(407, response->headers->response_code());
5140 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5141 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585142 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335143
5144 LoadTimingInfo load_timing_info;
5145 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5146
5147 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015148 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335149
5150 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115151 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335152}
5153
Asanka Herathbc3f8f62018-11-16 23:08:305154// This test exercises an odd edge case where the proxy closes the connection
5155// after the authentication handshake is complete. Presumably this technique is
5156// used in lieu of returning a 403 or 5xx status code when the authentication
5157// succeeds, but the user is not authorized to connect to the destination
5158// server. There's no standard for what a proxy should do to indicate a blocked
5159// site.
5160TEST_F(HttpNetworkTransactionTest,
5161 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5162 HttpRequestInfo request;
5163 request.method = "GET";
5164 request.url = GURL("https://www.example.org/");
5165 request.traffic_annotation =
5166 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5167
5168 // Configure against proxy server "myproxy:70".
5169 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565170 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Asanka Herathbc3f8f62018-11-16 23:08:305171 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5172
5173 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5174 auth_handler_factory->set_do_init_from_challenge(true);
5175
5176 // Create two mock AuthHandlers. This is because the transaction gets retried
5177 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5178 // was a real network error.
5179 //
5180 // The handlers support both default and explicit credentials. The retry
5181 // mentioned above should be able to reuse the default identity. Thus there
5182 // should never be a need to prompt for explicit credentials.
5183 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5184 mock_handler->set_allows_default_credentials(true);
5185 mock_handler->set_allows_explicit_credentials(true);
5186 mock_handler->set_connection_based(true);
5187 auth_handler_factory->AddMockHandler(mock_handler.release(),
5188 HttpAuth::AUTH_PROXY);
5189 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5190 mock_handler->set_allows_default_credentials(true);
5191 mock_handler->set_allows_explicit_credentials(true);
5192 mock_handler->set_connection_based(true);
5193 auth_handler_factory->AddMockHandler(mock_handler.release(),
5194 HttpAuth::AUTH_PROXY);
5195 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5196
Matt Muellerde5dadf2019-11-27 20:11:585197 session_deps_.net_log = NetLog::Get();
Asanka Herathbc3f8f62018-11-16 23:08:305198 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5199
5200 // Data for both sockets.
5201 //
5202 // Writes are for the tunnel establishment attempts and the
5203 // authentication handshake.
5204 MockWrite data_writes1[] = {
5205 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5206 "Host: www.example.org:443\r\n"
5207 "Proxy-Connection: keep-alive\r\n\r\n"),
5208
5209 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5210 "Host: www.example.org:443\r\n"
5211 "Proxy-Connection: keep-alive\r\n"
5212 "Proxy-Authorization: auth_token\r\n\r\n"),
5213
5214 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5215 "Host: www.example.org:443\r\n"
5216 "Proxy-Connection: keep-alive\r\n"
5217 "Proxy-Authorization: auth_token\r\n\r\n"),
5218 };
5219
5220 // The server side of the authentication handshake. Note that the response to
5221 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5222 MockRead data_reads1[] = {
5223 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5224 MockRead("Content-Length: 0\r\n"),
5225 MockRead("Proxy-Connection: keep-alive\r\n"),
5226 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5227
5228 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5229 MockRead("Content-Length: 0\r\n"),
5230 MockRead("Proxy-Connection: keep-alive\r\n"),
5231 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5232
5233 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5234 };
5235
5236 StaticSocketDataProvider data1(data_reads1, data_writes1);
5237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5238
5239 // The second socket is for the reconnection attempt. Data is identical to the
5240 // first attempt.
5241 StaticSocketDataProvider data2(data_reads1, data_writes1);
5242 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5243
5244 auto trans =
5245 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5246
5247 TestCompletionCallback callback;
5248 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5249
5250 // Two rounds per handshake. After one retry, the error is propagated up the
5251 // stack.
5252 for (int i = 0; i < 4; ++i) {
5253 EXPECT_THAT(callback.GetResult(rv), IsOk());
5254
5255 const HttpResponseInfo* response = trans->GetResponseInfo();
5256 ASSERT_TRUE(response);
5257 ASSERT_TRUE(response->headers);
5258 EXPECT_EQ(407, response->headers->response_code());
5259 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5260
5261 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5262 }
5263
5264 // One shall be the number thou shalt retry, and the number of the retrying
5265 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5266 // that thou then proceed to one. Three is right out. Once the number one,
5267 // being the first number, be reached, then lobbest thou thy
5268 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5269 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5270
5271 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115272 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Asanka Herathbc3f8f62018-11-16 23:08:305273}
5274
mmenke2a1781d2015-10-07 19:25:335275// Test a proxy auth scheme that allows default credentials and a proxy server
5276// that hangs up when credentials are initially sent, and sends a challenge
5277// again they are retried.
bncd16676a2016-07-20 16:23:015278TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335279 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5280 HttpRequestInfo request;
5281 request.method = "GET";
5282 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105283 request.traffic_annotation =
5284 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335285
5286 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595287 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565288 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495289 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335290
Jeremy Roman0579ed62017-08-29 15:56:195291 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335292 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195293 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335294 mock_handler->set_allows_default_credentials(true);
5295 auth_handler_factory->AddMockHandler(mock_handler.release(),
5296 HttpAuth::AUTH_PROXY);
5297 // Add another handler for the second challenge. It supports default
5298 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195299 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335300 mock_handler->set_allows_default_credentials(true);
5301 auth_handler_factory->AddMockHandler(mock_handler.release(),
5302 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485303 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335304
5305 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585306 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095307 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335308
5309 // Should try to establish tunnel.
5310 MockWrite data_writes1[] = {
5311 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175312 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335313 "Proxy-Connection: keep-alive\r\n\r\n"),
5314 };
5315
5316 // The proxy responds to the connect with a 407, using a non-persistent
5317 // connection.
5318 MockRead data_reads1[] = {
5319 // No credentials.
5320 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5321 MockRead("Proxy-Authenticate: Mock\r\n"),
5322 MockRead("Proxy-Connection: close\r\n\r\n"),
5323 };
5324
5325 // Since the first connection was closed, need to establish another once given
5326 // credentials.
5327 MockWrite data_writes2[] = {
5328 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175329 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335330 "Proxy-Connection: keep-alive\r\n"
5331 "Proxy-Authorization: auth_token\r\n\r\n"),
5332 };
5333
5334 MockRead data_reads2[] = {
5335 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5336 MockRead("Proxy-Authenticate: Mock\r\n"),
5337 MockRead("Proxy-Connection: close\r\n\r\n"),
5338 };
5339
Ryan Sleevib8d7ea02018-05-07 20:01:015340 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335341 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015342 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335343 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5344 SSLSocketDataProvider ssl(ASYNC, OK);
5345 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5346
bnc87dcefc2017-05-25 12:47:585347 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195348 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335349
5350 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205351 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015352 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335353
5354 const HttpResponseInfo* response = trans->GetResponseInfo();
5355 ASSERT_TRUE(response);
5356 ASSERT_TRUE(response->headers);
5357 EXPECT_EQ(407, response->headers->response_code());
5358 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5359 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585360 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335361
5362 LoadTimingInfo load_timing_info;
5363 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5364
5365 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015366 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335367 response = trans->GetResponseInfo();
5368 ASSERT_TRUE(response);
5369 ASSERT_TRUE(response->headers);
5370 EXPECT_EQ(407, response->headers->response_code());
5371 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585372 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335373
5374 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115375 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335376}
5377
asankae2257db2016-10-11 22:03:165378// A more nuanced test than GenerateAuthToken test which asserts that
5379// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5380// unnecessarily invalidated, and that if the server co-operates, the
5381// authentication handshake can continue with the same scheme but with a
5382// different identity.
5383TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5384 HttpRequestInfo request;
5385 request.method = "GET";
5386 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105387 request.traffic_annotation =
5388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165389
Jeremy Roman0579ed62017-08-29 15:56:195390 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165391 auth_handler_factory->set_do_init_from_challenge(true);
5392
5393 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195394 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165395 mock_handler->set_allows_default_credentials(true);
5396 mock_handler->set_allows_explicit_credentials(true);
5397 mock_handler->set_connection_based(true);
5398 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5399 auth_handler_factory->AddMockHandler(mock_handler.release(),
5400 HttpAuth::AUTH_SERVER);
5401
5402 // Add another handler for the second challenge. It supports default
5403 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195404 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165405 mock_handler->set_allows_default_credentials(true);
5406 mock_handler->set_allows_explicit_credentials(true);
5407 mock_handler->set_connection_based(true);
5408 auth_handler_factory->AddMockHandler(mock_handler.release(),
5409 HttpAuth::AUTH_SERVER);
5410 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5411
5412 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5413
5414 MockWrite data_writes1[] = {
5415 MockWrite("GET / HTTP/1.1\r\n"
5416 "Host: www.example.org\r\n"
5417 "Connection: keep-alive\r\n\r\n"),
5418 };
5419
5420 MockRead data_reads1[] = {
5421 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5422 "WWW-Authenticate: Mock\r\n"
5423 "Connection: keep-alive\r\n\r\n"),
5424 };
5425
5426 // Identical to data_writes1[]. The AuthHandler encounters a
5427 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5428 // transaction procceds without an authorization header.
5429 MockWrite data_writes2[] = {
5430 MockWrite("GET / HTTP/1.1\r\n"
5431 "Host: www.example.org\r\n"
5432 "Connection: keep-alive\r\n\r\n"),
5433 };
5434
5435 MockRead data_reads2[] = {
5436 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5437 "WWW-Authenticate: Mock\r\n"
5438 "Connection: keep-alive\r\n\r\n"),
5439 };
5440
5441 MockWrite data_writes3[] = {
5442 MockWrite("GET / HTTP/1.1\r\n"
5443 "Host: www.example.org\r\n"
5444 "Connection: keep-alive\r\n"
5445 "Authorization: auth_token\r\n\r\n"),
5446 };
5447
5448 MockRead data_reads3[] = {
5449 MockRead("HTTP/1.1 200 OK\r\n"
5450 "Content-Length: 5\r\n"
5451 "Content-Type: text/plain\r\n"
5452 "Connection: keep-alive\r\n\r\n"
5453 "Hello"),
5454 };
5455
Ryan Sleevib8d7ea02018-05-07 20:01:015456 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165457 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5458
Ryan Sleevib8d7ea02018-05-07 20:01:015459 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165460 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5461
Ryan Sleevib8d7ea02018-05-07 20:01:015462 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165463 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5464
bnc87dcefc2017-05-25 12:47:585465 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195466 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165467
5468 TestCompletionCallback callback;
5469 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5470 EXPECT_THAT(callback.GetResult(rv), IsOk());
5471
5472 const HttpResponseInfo* response = trans->GetResponseInfo();
5473 ASSERT_TRUE(response);
5474 ASSERT_TRUE(response->headers);
5475 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5476
5477 // The following three tests assert that an authentication challenge was
5478 // received and that the stack is ready to respond to the challenge using
5479 // ambient credentials.
5480 EXPECT_EQ(401, response->headers->response_code());
5481 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585482 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165483
5484 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5485 EXPECT_THAT(callback.GetResult(rv), IsOk());
5486 response = trans->GetResponseInfo();
5487 ASSERT_TRUE(response);
5488 ASSERT_TRUE(response->headers);
5489
5490 // The following three tests assert that an authentication challenge was
5491 // received and that the stack needs explicit credentials before it is ready
5492 // to respond to the challenge.
5493 EXPECT_EQ(401, response->headers->response_code());
5494 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585495 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165496
5497 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5498 EXPECT_THAT(callback.GetResult(rv), IsOk());
5499 response = trans->GetResponseInfo();
5500 ASSERT_TRUE(response);
5501 ASSERT_TRUE(response->headers);
5502 EXPECT_EQ(200, response->headers->response_code());
5503
5504 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115505 session->CloseAllConnections(ERR_FAILED, "Very good reason");
asankae2257db2016-10-11 22:03:165506}
5507
Matt Menked1eb6d42018-01-17 04:54:065508// Proxy resolver that returns a proxy with the same host and port for different
5509// schemes, based on the path of the URL being requests.
5510class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5511 public:
5512 SameProxyWithDifferentSchemesProxyResolver() {}
5513 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5514
5515 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
5516
5517 static HostPortPair ProxyHostPortPair() {
5518 return HostPortPair::FromString(ProxyHostPortPairAsString());
5519 }
5520
5521 // ProxyResolver implementation.
5522 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:395523 const NetworkIsolationKey& network_isolation_key,
Matt Menked1eb6d42018-01-17 04:54:065524 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175525 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065526 std::unique_ptr<Request>* request,
5527 const NetLogWithSource& /*net_log*/) override {
5528 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575529 results->set_traffic_annotation(
5530 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065531 if (url.path() == "/socks4") {
5532 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5533 return OK;
5534 }
5535 if (url.path() == "/socks5") {
5536 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5537 return OK;
5538 }
5539 if (url.path() == "/http") {
5540 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5541 return OK;
5542 }
5543 if (url.path() == "/https") {
5544 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5545 return OK;
5546 }
Matt Menkee8648fa2019-01-17 16:47:075547 if (url.path() == "/https_trusted") {
5548 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5549 ProxyHostPortPair(),
5550 true /* is_trusted_proxy */));
5551 return OK;
5552 }
Matt Menked1eb6d42018-01-17 04:54:065553 NOTREACHED();
5554 return ERR_NOT_IMPLEMENTED;
5555 }
5556
5557 private:
5558 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5559};
5560
5561class SameProxyWithDifferentSchemesProxyResolverFactory
5562 : public ProxyResolverFactory {
5563 public:
5564 SameProxyWithDifferentSchemesProxyResolverFactory()
5565 : ProxyResolverFactory(false) {}
5566
Lily Houghton99597862018-03-07 16:40:425567 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5568 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175569 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425570 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065571 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5572 return OK;
5573 }
5574
5575 private:
5576 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5577};
5578
5579// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075580// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065581// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5582// request to foo.com using proxy.com as an HTTP proxy.
5583TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495584 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565585 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:495586 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5587 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5588 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
Eric Roman3be01ba2020-04-03 21:37:095589 nullptr, /*quick_check_enabled=*/true);
Matt Menked1eb6d42018-01-17 04:54:065590
5591 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5592
5593 MockWrite socks_writes[] = {
5594 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5595 kSOCKS4OkRequestLocalHostPort80Length),
5596 MockWrite(SYNCHRONOUS,
5597 "GET /socks4 HTTP/1.1\r\n"
5598 "Host: test\r\n"
5599 "Connection: keep-alive\r\n\r\n"),
5600 };
5601 MockRead socks_reads[] = {
5602 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5603 MockRead("HTTP/1.0 200 OK\r\n"
5604 "Connection: keep-alive\r\n"
5605 "Content-Length: 15\r\n\r\n"
5606 "SOCKS4 Response"),
5607 };
Ryan Sleevib8d7ea02018-05-07 20:01:015608 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065609 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5610
5611 const char kSOCKS5Request[] = {
5612 0x05, // Version
5613 0x01, // Command (CONNECT)
5614 0x00, // Reserved
5615 0x03, // Address type (DOMAINNAME)
5616 0x04, // Length of domain (4)
5617 't', 'e', 's', 't', // Domain string
5618 0x00, 0x50, // 16-bit port (80)
5619 };
5620 MockWrite socks5_writes[] = {
5621 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245622 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065623 MockWrite(SYNCHRONOUS,
5624 "GET /socks5 HTTP/1.1\r\n"
5625 "Host: test\r\n"
5626 "Connection: keep-alive\r\n\r\n"),
5627 };
5628 MockRead socks5_reads[] = {
5629 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5630 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5631 MockRead("HTTP/1.0 200 OK\r\n"
5632 "Connection: keep-alive\r\n"
5633 "Content-Length: 15\r\n\r\n"
5634 "SOCKS5 Response"),
5635 };
Ryan Sleevib8d7ea02018-05-07 20:01:015636 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065637 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5638
5639 MockWrite http_writes[] = {
5640 MockWrite(SYNCHRONOUS,
5641 "GET http://test/http HTTP/1.1\r\n"
5642 "Host: test\r\n"
5643 "Proxy-Connection: keep-alive\r\n\r\n"),
5644 };
5645 MockRead http_reads[] = {
5646 MockRead("HTTP/1.1 200 OK\r\n"
5647 "Proxy-Connection: keep-alive\r\n"
5648 "Content-Length: 13\r\n\r\n"
5649 "HTTP Response"),
5650 };
Ryan Sleevib8d7ea02018-05-07 20:01:015651 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065652 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5653
5654 MockWrite https_writes[] = {
5655 MockWrite(SYNCHRONOUS,
5656 "GET http://test/https HTTP/1.1\r\n"
5657 "Host: test\r\n"
5658 "Proxy-Connection: keep-alive\r\n\r\n"),
5659 };
5660 MockRead https_reads[] = {
5661 MockRead("HTTP/1.1 200 OK\r\n"
5662 "Proxy-Connection: keep-alive\r\n"
5663 "Content-Length: 14\r\n\r\n"
5664 "HTTPS Response"),
5665 };
Ryan Sleevib8d7ea02018-05-07 20:01:015666 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065667 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5668 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5670
Matt Menkee8648fa2019-01-17 16:47:075671 MockWrite https_trusted_writes[] = {
5672 MockWrite(SYNCHRONOUS,
5673 "GET http://test/https_trusted HTTP/1.1\r\n"
5674 "Host: test\r\n"
5675 "Proxy-Connection: keep-alive\r\n\r\n"),
5676 };
5677 MockRead https_trusted_reads[] = {
5678 MockRead("HTTP/1.1 200 OK\r\n"
5679 "Proxy-Connection: keep-alive\r\n"
5680 "Content-Length: 22\r\n\r\n"
5681 "HTTPS Trusted Response"),
5682 };
5683 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5684 https_trusted_writes);
5685 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5686 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5688
Matt Menked1eb6d42018-01-17 04:54:065689 struct TestCase {
5690 GURL url;
5691 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075692 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065693 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075694 int expected_idle_socks4_sockets;
5695 int expected_idle_socks5_sockets;
5696 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5697 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065698 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075699 int expected_idle_https_sockets;
5700 // How many idle sockets there should be in the HTTPS proxy socket pool with
5701 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5702 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065703 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075704 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5705 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5706 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5707 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5708 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5709 1},
Matt Menked1eb6d42018-01-17 04:54:065710 };
5711
5712 for (const auto& test_case : kTestCases) {
5713 HttpRequestInfo request;
5714 request.method = "GET";
5715 request.url = test_case.url;
Ramin Halavatib5e433e2018-02-07 07:41:105716 request.traffic_annotation =
5717 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065718 std::unique_ptr<HttpNetworkTransaction> trans =
5719 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5720 session.get());
5721 TestCompletionCallback callback;
5722 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5723 EXPECT_THAT(callback.GetResult(rv), IsOk());
5724
5725 const HttpResponseInfo* response = trans->GetResponseInfo();
5726 ASSERT_TRUE(response);
5727 ASSERT_TRUE(response->headers);
5728 EXPECT_EQ(200, response->headers->response_code());
5729 std::string response_data;
5730 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5731 EXPECT_EQ(test_case.expected_response, response_data);
5732
5733 // Return the socket to the socket pool, so can make sure it's not used for
5734 // the next requests.
5735 trans.reset();
5736 base::RunLoop().RunUntilIdle();
5737
5738 // Check the number of idle sockets in the pool, to make sure that used
5739 // sockets are indeed being returned to the socket pool. If each request
5740 // doesn't return an idle socket to the pool, the test would incorrectly
5741 // pass.
Matt Menkee8648fa2019-01-17 16:47:075742 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5743 session
Matt Menked23ab952019-03-06 00:24:405744 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075745 HttpNetworkSession::NORMAL_SOCKET_POOL,
5746 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5747 SameProxyWithDifferentSchemesProxyResolver::
5748 ProxyHostPortPair()))
5749 ->IdleSocketCount());
5750 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5751 session
Matt Menked23ab952019-03-06 00:24:405752 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075753 HttpNetworkSession::NORMAL_SOCKET_POOL,
5754 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5755 SameProxyWithDifferentSchemesProxyResolver::
5756 ProxyHostPortPair()))
5757 ->IdleSocketCount());
5758 EXPECT_EQ(test_case.expected_idle_http_sockets,
5759 session
Matt Menked23ab952019-03-06 00:24:405760 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075761 HttpNetworkSession::NORMAL_SOCKET_POOL,
5762 ProxyServer(ProxyServer::SCHEME_HTTP,
5763 SameProxyWithDifferentSchemesProxyResolver::
5764 ProxyHostPortPair()))
5765 ->IdleSocketCount());
5766 EXPECT_EQ(test_case.expected_idle_https_sockets,
5767 session
Matt Menked23ab952019-03-06 00:24:405768 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075769 HttpNetworkSession::NORMAL_SOCKET_POOL,
5770 ProxyServer(ProxyServer::SCHEME_HTTPS,
5771 SameProxyWithDifferentSchemesProxyResolver::
5772 ProxyHostPortPair()))
5773 ->IdleSocketCount());
5774 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5775 session
Matt Menked23ab952019-03-06 00:24:405776 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075777 HttpNetworkSession::NORMAL_SOCKET_POOL,
5778 ProxyServer(ProxyServer::SCHEME_HTTPS,
5779 SameProxyWithDifferentSchemesProxyResolver::
5780 ProxyHostPortPair(),
5781 true /* is_trusted_proxy */))
5782 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065783 }
5784}
5785
[email protected]029c83b62013-01-24 05:28:205786// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015787TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205788 HttpRequestInfo request1;
5789 request1.method = "GET";
bncce36dca22015-04-21 22:11:235790 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105791 request1.traffic_annotation =
5792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205793
5794 HttpRequestInfo request2;
5795 request2.method = "GET";
bncce36dca22015-04-21 22:11:235796 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105797 request2.traffic_annotation =
5798 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205799
5800 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:565801 session_deps_.proxy_resolution_service =
5802 ConfiguredProxyResolutionService::CreateFixed(
5803 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145804 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075805 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095806 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205807
5808 // Since we have proxy, should try to establish tunnel.
5809 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175810 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5811 "Host: www.example.org:443\r\n"
5812 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205813
rsleevidb16bb02015-11-12 23:47:175814 MockWrite("GET /1 HTTP/1.1\r\n"
5815 "Host: www.example.org\r\n"
5816 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205817
rsleevidb16bb02015-11-12 23:47:175818 MockWrite("GET /2 HTTP/1.1\r\n"
5819 "Host: www.example.org\r\n"
5820 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205821 };
5822
5823 // The proxy responds to the connect with a 407, using a persistent
5824 // connection.
5825 MockRead data_reads1[] = {
5826 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5827
5828 MockRead("HTTP/1.1 200 OK\r\n"),
5829 MockRead("Content-Length: 1\r\n\r\n"),
5830 MockRead(SYNCHRONOUS, "1"),
5831
5832 MockRead("HTTP/1.1 200 OK\r\n"),
5833 MockRead("Content-Length: 2\r\n\r\n"),
5834 MockRead(SYNCHRONOUS, "22"),
5835 };
5836
Ryan Sleevib8d7ea02018-05-07 20:01:015837 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075838 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205839 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075840 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205841
5842 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585843 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195844 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205845
5846 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015847 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205848
5849 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015850 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205851
5852 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525853 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475854 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525855 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205856 EXPECT_EQ(1, response1->headers->GetContentLength());
5857
5858 LoadTimingInfo load_timing_info1;
5859 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5860 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5861
5862 trans1.reset();
5863
5864 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585865 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195866 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205867
5868 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205870
5871 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015872 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205873
5874 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525875 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475876 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525877 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205878 EXPECT_EQ(2, response2->headers->GetContentLength());
5879
5880 LoadTimingInfo load_timing_info2;
5881 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5882 TestLoadTimingReused(load_timing_info2);
5883
5884 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5885
5886 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:115887 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:205888}
5889
5890// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015891TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205892 HttpRequestInfo request1;
5893 request1.method = "GET";
bncce36dca22015-04-21 22:11:235894 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105895 request1.traffic_annotation =
5896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205897
5898 HttpRequestInfo request2;
5899 request2.method = "GET";
bncce36dca22015-04-21 22:11:235900 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105901 request2.traffic_annotation =
5902 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205903
5904 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595905 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565906 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495907 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145908 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075909 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095910 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205911
5912 // Since we have proxy, should try to establish tunnel.
5913 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175914 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5915 "Host: www.example.org:443\r\n"
5916 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205917
rsleevidb16bb02015-11-12 23:47:175918 MockWrite("GET /1 HTTP/1.1\r\n"
5919 "Host: www.example.org\r\n"
5920 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205921
rsleevidb16bb02015-11-12 23:47:175922 MockWrite("GET /2 HTTP/1.1\r\n"
5923 "Host: www.example.org\r\n"
5924 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205925 };
5926
5927 // The proxy responds to the connect with a 407, using a persistent
5928 // connection.
5929 MockRead data_reads1[] = {
5930 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5931
5932 MockRead("HTTP/1.1 200 OK\r\n"),
5933 MockRead("Content-Length: 1\r\n\r\n"),
5934 MockRead(SYNCHRONOUS, "1"),
5935
5936 MockRead("HTTP/1.1 200 OK\r\n"),
5937 MockRead("Content-Length: 2\r\n\r\n"),
5938 MockRead(SYNCHRONOUS, "22"),
5939 };
5940
Ryan Sleevib8d7ea02018-05-07 20:01:015941 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075942 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205943 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205945
5946 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585947 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195948 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205949
5950 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015951 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205952
5953 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015954 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205955
5956 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525957 ASSERT_TRUE(response1);
5958 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205959 EXPECT_EQ(1, response1->headers->GetContentLength());
5960
5961 LoadTimingInfo load_timing_info1;
5962 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5963 TestLoadTimingNotReusedWithPac(load_timing_info1,
5964 CONNECT_TIMING_HAS_SSL_TIMES);
5965
5966 trans1.reset();
5967
5968 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585969 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195970 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205971
5972 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015973 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205974
5975 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015976 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205977
5978 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525979 ASSERT_TRUE(response2);
5980 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205981 EXPECT_EQ(2, response2->headers->GetContentLength());
5982
5983 LoadTimingInfo load_timing_info2;
5984 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5985 TestLoadTimingReusedWithPac(load_timing_info2);
5986
5987 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5988
5989 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:115990 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:205991}
5992
Matt Menke8045afd2019-11-14 20:31:195993// Make sure that NetworkIsolationKeys are passed down to the proxy layer.
5994TEST_F(HttpNetworkTransactionTest, ProxyResolvedWithNetworkIsolationKey) {
5995 const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
5996 const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
5997
5998 ProxyConfig proxy_config;
5999 proxy_config.set_auto_detect(true);
6000 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6001
6002 CapturingProxyResolver capturing_proxy_resolver;
6003 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6004 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566005 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke8045afd2019-11-14 20:31:196006 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6007 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6008 std::make_unique<CapturingProxyResolverFactory>(
6009 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096010 nullptr, /*quick_check_enabled=*/true);
Matt Menke8045afd2019-11-14 20:31:196011
6012 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6013
6014 // No need to continue with the network request - proxy resolution occurs
6015 // before establishing a data.
6016 StaticSocketDataProvider data{base::span<MockRead>(),
6017 base::span<MockWrite>()};
6018 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
6019 session_deps_.socket_factory->AddSocketDataProvider(&data);
6020
6021 // Run first request until an auth challenge is observed.
6022 HttpRequestInfo request;
6023 request.method = "GET";
6024 request.url = GURL("http://foo.test/");
6025 request.traffic_annotation =
6026 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6027 HttpNetworkTransaction trans(LOWEST, session.get());
6028 TestCompletionCallback callback;
6029 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6030 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
6031}
6032
dalyk6d7a8c52019-12-18 21:43:016033// Test that a failure in resolving the proxy hostname is retrievable.
6034TEST_F(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
6035 HttpRequestInfo request;
6036 request.method = "GET";
6037 request.url = GURL("http://www.example.org/");
6038 request.traffic_annotation =
6039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6040
6041 RecordingTestNetLog log;
6042 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566043 session_deps_.proxy_resolution_service =
6044 ConfiguredProxyResolutionService::CreateFixed(
6045 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
dalyk6d7a8c52019-12-18 21:43:016046 MockHostResolver* resolver = new MockHostResolver();
6047 resolver->rules()->AddSimulatedTimeoutFailure("proxy");
6048 session_deps_.net_log = &log;
6049 session_deps_.host_resolver.reset(resolver);
6050 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6051 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6052 TestCompletionCallback callback;
6053
6054 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6055 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6056 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
6057
6058 const HttpResponseInfo* response = trans.GetResponseInfo();
6059 ASSERT_TRUE(response);
6060 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
6061}
6062
[email protected]2df19bb2010-08-25 20:13:466063// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016064TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276065 HttpRequestInfo request;
6066 request.method = "GET";
bncce36dca22015-04-21 22:11:236067 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106068 request.traffic_annotation =
6069 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276070
[email protected]2df19bb2010-08-25 20:13:466071 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566072 session_deps_.proxy_resolution_service =
6073 ConfiguredProxyResolutionService::CreateFixed(
6074 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146075 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076076 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466078
[email protected]2df19bb2010-08-25 20:13:466079 // Since we have proxy, should use full url
6080 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236081 MockWrite(
6082 "GET http://www.example.org/ HTTP/1.1\r\n"
6083 "Host: www.example.org\r\n"
6084 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466085 };
6086
6087 MockRead data_reads1[] = {
6088 MockRead("HTTP/1.1 200 OK\r\n"),
6089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6090 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066091 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466092 };
6093
Ryan Sleevib8d7ea02018-05-07 20:01:016094 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076095 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066096 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466098
[email protected]49639fa2011-12-20 23:22:416099 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466100
bnc691fda62016-08-12 00:43:166101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506102
bnc691fda62016-08-12 00:43:166103 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466105
6106 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016107 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466108
[email protected]58e32bb2013-01-21 18:23:256109 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166110 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256111 TestLoadTimingNotReused(load_timing_info,
6112 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6113
bnc691fda62016-08-12 00:43:166114 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526115 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466116
tbansal2ecbbc72016-10-06 17:15:476117 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466118 EXPECT_TRUE(response->headers->IsKeepAlive());
6119 EXPECT_EQ(200, response->headers->response_code());
6120 EXPECT_EQ(100, response->headers->GetContentLength());
6121 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6122
6123 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586124 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466125}
6126
[email protected]7642b5ae2010-09-01 20:55:176127// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016128TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276129 HttpRequestInfo request;
6130 request.method = "GET";
bncce36dca22015-04-21 22:11:236131 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106132 request.traffic_annotation =
6133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276134
[email protected]7642b5ae2010-09-01 20:55:176135 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566136 session_deps_.proxy_resolution_service =
6137 ConfiguredProxyResolutionService::CreateFixed(
6138 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146139 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076140 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096141 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176142
bncce36dca22015-04-21 22:11:236143 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136144 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456145 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416146 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176147
Ryan Hamilton0239aac2018-05-19 00:03:136148 spdy::SpdySerializedFrame resp(
6149 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6150 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176151 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416152 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176153 };
6154
Ryan Sleevib8d7ea02018-05-07 20:01:016155 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076156 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176157
[email protected]8ddf8322012-02-23 18:08:066158 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366159 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176161
[email protected]49639fa2011-12-20 23:22:416162 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176163
bnc691fda62016-08-12 00:43:166164 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506165
bnc691fda62016-08-12 00:43:166166 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176168
6169 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016170 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176171
[email protected]58e32bb2013-01-21 18:23:256172 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166173 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256174 TestLoadTimingNotReused(load_timing_info,
6175 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6176
bnc691fda62016-08-12 00:43:166177 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526178 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476179 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526180 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026181 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176182
6183 std::string response_data;
bnc691fda62016-08-12 00:43:166184 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236185 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176186}
6187
[email protected]1c173852014-06-19 12:51:506188// Verifies that a session which races and wins against the owning transaction
6189// (completing prior to host resolution), doesn't fail the transaction.
6190// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016191TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506192 HttpRequestInfo request;
6193 request.method = "GET";
bncce36dca22015-04-21 22:11:236194 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106195 request.traffic_annotation =
6196 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506197
6198 // Configure SPDY proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566199 session_deps_.proxy_resolution_service =
6200 ConfiguredProxyResolutionService::CreateFixed(
6201 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146202 RecordingBoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506203 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506205
bncce36dca22015-04-21 22:11:236206 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136207 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456208 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416209 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506210
Raul Tambre94493c652019-03-11 17:18:356211 spdy::SpdySerializedFrame resp(
6212 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136213 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506214 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416215 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506216 };
6217
Ryan Sleevib8d7ea02018-05-07 20:01:016218 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506219 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6220
6221 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366222 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6224
6225 TestCompletionCallback callback1;
6226
bnc691fda62016-08-12 00:43:166227 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506228
6229 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506230 session_deps_.host_resolver->set_ondemand_mode(true);
6231
bnc691fda62016-08-12 00:43:166232 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016233 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506234
6235 // Race a session to the proxy, which completes first.
6236 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046237 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116238 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346239 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6240 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506241 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526242 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506243
6244 // Unstall the resolution begun by the transaction.
6245 session_deps_.host_resolver->set_ondemand_mode(true);
6246 session_deps_.host_resolver->ResolveAllPending();
6247
6248 EXPECT_FALSE(callback1.have_result());
6249 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016250 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506251
bnc691fda62016-08-12 00:43:166252 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526253 ASSERT_TRUE(response);
6254 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026255 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506256
6257 std::string response_data;
bnc691fda62016-08-12 00:43:166258 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506259 EXPECT_EQ(kUploadData, response_data);
6260}
6261
[email protected]dc7bd1c52010-11-12 00:01:136262// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016263TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276264 HttpRequestInfo request;
6265 request.method = "GET";
bncce36dca22015-04-21 22:11:236266 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106267 request.traffic_annotation =
6268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276269
[email protected]79cb5c12011-09-12 13:12:046270 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566271 session_deps_.proxy_resolution_service =
6272 ConfiguredProxyResolutionService::CreateFixed(
6273 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146274 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076275 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096276 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136277
[email protected]dc7bd1c52010-11-12 00:01:136278 // The first request will be a bare GET, the second request will be a
6279 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456280 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136281 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486282 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386283 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136284 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466285 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136286 };
Ryan Hamilton0239aac2018-05-19 00:03:136287 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246288 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486289 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136290 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416291 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136292 };
6293
6294 // The first response is a 407 proxy authentication challenge, and the second
6295 // response will be a 200 response since the second request includes a valid
6296 // Authorization header.
6297 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466298 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136299 };
Ryan Hamilton0239aac2018-05-19 00:03:136300 spdy::SpdySerializedFrame resp_authentication(
6301 spdy_util_.ConstructSpdyReplyError(
6302 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246303 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136304 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416305 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136306 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356307 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136308 spdy::SpdySerializedFrame body_data(
6309 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136310 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416311 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466312 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416313 CreateMockRead(resp_data, 4),
6314 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136315 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136316 };
6317
Ryan Sleevib8d7ea02018-05-07 20:01:016318 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076319 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136320
[email protected]8ddf8322012-02-23 18:08:066321 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366322 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076323 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136324
[email protected]49639fa2011-12-20 23:22:416325 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136326
bnc691fda62016-08-12 00:43:166327 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136328
bnc691fda62016-08-12 00:43:166329 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136331
6332 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016333 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136334
bnc691fda62016-08-12 00:43:166335 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136336
wezca1070932016-05-26 20:30:526337 ASSERT_TRUE(response);
6338 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136339 EXPECT_EQ(407, response->headers->response_code());
6340 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586341 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136342
[email protected]49639fa2011-12-20 23:22:416343 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136344
bnc691fda62016-08-12 00:43:166345 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016346 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136347
6348 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016349 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136350
bnc691fda62016-08-12 00:43:166351 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136352
wezca1070932016-05-26 20:30:526353 ASSERT_TRUE(response_restart);
6354 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136355 EXPECT_EQ(200, response_restart->headers->response_code());
6356 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586357 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136358}
6359
[email protected]d9da5fe2010-10-13 22:37:166360// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016361TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276362 HttpRequestInfo request;
6363 request.method = "GET";
bncce36dca22015-04-21 22:11:236364 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106365 request.traffic_annotation =
6366 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276367
[email protected]d9da5fe2010-10-13 22:37:166368 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566369 session_deps_.proxy_resolution_service =
6370 ConfiguredProxyResolutionService::CreateFixed(
6371 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146372 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076373 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166375
bnc691fda62016-08-12 00:43:166376 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166377
bncce36dca22015-04-21 22:11:236378 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136379 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046380 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6381 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236382 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166383
bncce36dca22015-04-21 22:11:236384 const char get[] =
6385 "GET / HTTP/1.1\r\n"
6386 "Host: www.example.org\r\n"
6387 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136388 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196389 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136390 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356391 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166392 const char resp[] = "HTTP/1.1 200 OK\r\n"
6393 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136394 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196395 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136396 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196397 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136398 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416399 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046400
6401 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416402 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6403 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046404 };
6405
[email protected]d9da5fe2010-10-13 22:37:166406 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416407 CreateMockRead(conn_resp, 1, ASYNC),
6408 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6409 CreateMockRead(wrapped_body, 4, ASYNC),
6410 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136411 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166412 };
6413
Ryan Sleevib8d7ea02018-05-07 20:01:016414 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076415 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166416
[email protected]8ddf8322012-02-23 18:08:066417 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366418 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066420 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166422
[email protected]49639fa2011-12-20 23:22:416423 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166424
bnc691fda62016-08-12 00:43:166425 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016426 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166427
6428 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016429 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166430
[email protected]58e32bb2013-01-21 18:23:256431 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166432 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256433 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6434
bnc691fda62016-08-12 00:43:166435 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526436 ASSERT_TRUE(response);
6437 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166438 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6439
6440 std::string response_data;
bnc691fda62016-08-12 00:43:166441 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166442 EXPECT_EQ("1234567890", response_data);
6443}
6444
6445// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016446TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6447 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386448
[email protected]cb9bf6ca2011-01-28 13:15:276449 HttpRequestInfo request;
6450 request.method = "GET";
bncce36dca22015-04-21 22:11:236451 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106452 request.traffic_annotation =
6453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276454
[email protected]d9da5fe2010-10-13 22:37:166455 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566456 session_deps_.proxy_resolution_service =
6457 ConfiguredProxyResolutionService::CreateFixed(
6458 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146459 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076460 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096461 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166462
bnc691fda62016-08-12 00:43:166463 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166464
bncce36dca22015-04-21 22:11:236465 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136466 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046467 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6468 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236469 // fetch https://www.example.org/ via SPDY
6470 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136471 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496472 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136473 spdy::SpdySerializedFrame wrapped_get(
6474 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6475 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356476 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136477 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356478 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136479 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026480 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136481 spdy::SpdySerializedFrame body(
6482 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6483 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026484 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136485 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416486 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136487 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416488 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046489
6490 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416491 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6492 CreateMockWrite(window_update_get_resp, 6),
6493 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046494 };
6495
[email protected]d9da5fe2010-10-13 22:37:166496 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416497 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096498 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416499 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6500 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136501 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166502 };
6503
Ryan Sleevib8d7ea02018-05-07 20:01:016504 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076505 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166506
[email protected]8ddf8322012-02-23 18:08:066507 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366508 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076509 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066510 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366511 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166513
[email protected]49639fa2011-12-20 23:22:416514 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166515
bnc691fda62016-08-12 00:43:166516 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016517 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166518
rch32320842015-05-16 15:57:096519 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556520 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096521 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596522 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166523 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016524 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166525
[email protected]58e32bb2013-01-21 18:23:256526 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166527 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256528 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6529
bnc691fda62016-08-12 00:43:166530 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526531 ASSERT_TRUE(response);
6532 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026533 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166534
6535 std::string response_data;
bnc691fda62016-08-12 00:43:166536 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236537 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166538}
6539
6540// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016541TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276542 HttpRequestInfo request;
6543 request.method = "GET";
bncce36dca22015-04-21 22:11:236544 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106545 request.traffic_annotation =
6546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276547
[email protected]d9da5fe2010-10-13 22:37:166548 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566549 session_deps_.proxy_resolution_service =
6550 ConfiguredProxyResolutionService::CreateFixed(
6551 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146552 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076553 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096554 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166555
bnc691fda62016-08-12 00:43:166556 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166557
bncce36dca22015-04-21 22:11:236558 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136559 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046560 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6561 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136562 spdy::SpdySerializedFrame get(
6563 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166564
6565 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416566 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166567 };
6568
Ryan Hamilton0239aac2018-05-19 00:03:136569 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6570 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166571 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416572 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166573 };
6574
Ryan Sleevib8d7ea02018-05-07 20:01:016575 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076576 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166577
[email protected]8ddf8322012-02-23 18:08:066578 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366579 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066581 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366582 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166584
[email protected]49639fa2011-12-20 23:22:416585 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166586
bnc691fda62016-08-12 00:43:166587 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016588 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166589
6590 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016591 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166592
ttuttle960fcbf2016-04-19 13:26:326593 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166594}
6595
Matt Menkecb2cd0982018-12-19 17:54:046596// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246597// is observed, but does exist by the time auth credentials are provided. In
6598// this case, auth and SSL are fully negotated on the second request, but then
6599// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046600TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6601 ProxyConfig proxy_config;
6602 proxy_config.set_auto_detect(true);
6603 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6604
6605 CapturingProxyResolver capturing_proxy_resolver;
6606 capturing_proxy_resolver.set_proxy_server(
6607 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6608 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566609 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menkecb2cd0982018-12-19 17:54:046610 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6611 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6612 std::make_unique<CapturingProxyResolverFactory>(
6613 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096614 nullptr, /*quick_check_enabled=*/true);
Matt Menkecb2cd0982018-12-19 17:54:046615
6616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6617
6618 const char kMyUrl[] = "https://www.example.org/";
6619 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6620 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356621 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046622 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6623
6624 spdy_util_.UpdateWithStreamDestruction(1);
6625 spdy::SpdySerializedFrame get2(
6626 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6627 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356628 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046629 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6630
6631 MockWrite auth_challenge_writes[] = {
6632 MockWrite(ASYNC, 0,
6633 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6634 "Host: www.example.org:443\r\n"
6635 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246636 MockWrite(ASYNC, 2,
6637 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6638 "Host: www.example.org:443\r\n"
6639 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046640 };
6641
6642 MockRead auth_challenge_reads[] = {
6643 MockRead(ASYNC, 1,
6644 "HTTP/1.1 407 Authentication Required\r\n"
6645 "Content-Length: 0\r\n"
6646 "Proxy-Connection: close\r\n"
6647 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6648 };
6649
6650 MockWrite spdy_writes[] = {
6651 MockWrite(ASYNC, 0,
6652 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6653 "Host: www.example.org:443\r\n"
6654 "Proxy-Connection: keep-alive\r\n"
6655 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6656 CreateMockWrite(get, 2),
6657 CreateMockWrite(get2, 5),
6658 };
6659
6660 MockRead spdy_reads[] = {
6661 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6662 CreateMockRead(get_resp, 3, ASYNC),
6663 CreateMockRead(body, 4, ASYNC),
6664 CreateMockRead(get_resp2, 6, ASYNC),
6665 CreateMockRead(body2, 7, ASYNC),
6666
6667 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6668 };
6669
Matt Menke5062be22019-05-01 17:50:246670 MockWrite auth_response_writes_discarded_socket[] = {
6671 MockWrite(ASYNC, 0,
6672 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6673 "Host: www.example.org:443\r\n"
6674 "Proxy-Connection: keep-alive\r\n"
6675 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6676 };
6677
6678 MockRead auth_response_reads_discarded_socket[] = {
6679 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6680 };
6681
Matt Menkecb2cd0982018-12-19 17:54:046682 SequencedSocketData auth_challenge1(auth_challenge_reads,
6683 auth_challenge_writes);
6684 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6685
6686 SequencedSocketData auth_challenge2(auth_challenge_reads,
6687 auth_challenge_writes);
6688 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6689
6690 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6691 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6692
Matt Menke5062be22019-05-01 17:50:246693 SequencedSocketData auth_response_discarded_socket(
6694 auth_response_reads_discarded_socket,
6695 auth_response_writes_discarded_socket);
6696 session_deps_.socket_factory->AddSocketDataProvider(
6697 &auth_response_discarded_socket);
6698
Matt Menkecb2cd0982018-12-19 17:54:046699 SSLSocketDataProvider ssl(ASYNC, OK);
6700 ssl.next_proto = kProtoHTTP2;
6701 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6702
Matt Menke5062be22019-05-01 17:50:246703 SSLSocketDataProvider ssl2(ASYNC, OK);
6704 ssl2.next_proto = kProtoHTTP2;
6705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6706
Matt Menkecb2cd0982018-12-19 17:54:046707 TestCompletionCallback callback;
6708 std::string response_data;
6709
6710 // Run first request until an auth challenge is observed.
6711 HttpRequestInfo request1;
6712 request1.method = "GET";
6713 request1.url = GURL(kMyUrl);
6714 request1.traffic_annotation =
6715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6716 HttpNetworkTransaction trans1(LOWEST, session.get());
6717 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6718 EXPECT_THAT(callback.GetResult(rv), IsOk());
6719 const HttpResponseInfo* response = trans1.GetResponseInfo();
6720 ASSERT_TRUE(response);
6721 ASSERT_TRUE(response->headers);
6722 EXPECT_EQ(407, response->headers->response_code());
6723 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586724 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046725
6726 // Run second request until an auth challenge is observed.
6727 HttpRequestInfo request2;
6728 request2.method = "GET";
6729 request2.url = GURL(kMyUrl);
6730 request2.traffic_annotation =
6731 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6732 HttpNetworkTransaction trans2(LOWEST, session.get());
6733 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6734 EXPECT_THAT(callback.GetResult(rv), IsOk());
6735 response = trans2.GetResponseInfo();
6736 ASSERT_TRUE(response);
6737 ASSERT_TRUE(response->headers);
6738 EXPECT_EQ(407, response->headers->response_code());
6739 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586740 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046741
6742 // Now provide credentials for the first request, and wait for it to complete.
6743 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6744 rv = callback.GetResult(rv);
6745 EXPECT_THAT(rv, IsOk());
6746 response = trans1.GetResponseInfo();
6747 ASSERT_TRUE(response);
6748 ASSERT_TRUE(response->headers);
6749 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6750 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6751 EXPECT_EQ(kUploadData, response_data);
6752
6753 // Now provide credentials for the second request. It should notice the
6754 // existing session, and reuse it.
6755 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6756 EXPECT_THAT(callback.GetResult(rv), IsOk());
6757 response = trans2.GetResponseInfo();
6758 ASSERT_TRUE(response);
6759 ASSERT_TRUE(response->headers);
6760 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6761 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6762 EXPECT_EQ(kUploadData, response_data);
6763}
6764
[email protected]f6c63db52013-02-02 00:35:226765// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6766// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016767TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226768 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6769 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566770 session_deps_.proxy_resolution_service =
6771 ConfiguredProxyResolutionService::CreateFixed(
6772 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146773 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076774 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096775 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506776 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226777
6778 HttpRequestInfo request1;
6779 request1.method = "GET";
bncce36dca22015-04-21 22:11:236780 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226781 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106782 request1.traffic_annotation =
6783 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226784
6785 HttpRequestInfo request2;
6786 request2.method = "GET";
bncce36dca22015-04-21 22:11:236787 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226788 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106789 request2.traffic_annotation =
6790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226791
bncce36dca22015-04-21 22:11:236792 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136793 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046794 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6795 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136796 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356797 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226798
bncce36dca22015-04-21 22:11:236799 // Fetch https://www.example.org/ via HTTP.
6800 const char get1[] =
6801 "GET / HTTP/1.1\r\n"
6802 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226803 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136804 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196805 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226806 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6807 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136808 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196809 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136810 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196811 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136812 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416813 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226814
bncce36dca22015-04-21 22:11:236815 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136816 spdy::SpdyHeaderBlock connect2_block;
6817 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6818 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6819 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046820 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6821 false));
[email protected]601e03f12014-04-06 16:26:396822
Ryan Hamilton0239aac2018-05-19 00:03:136823 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356824 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226825
bncce36dca22015-04-21 22:11:236826 // Fetch https://mail.example.org/ via HTTP.
6827 const char get2[] =
6828 "GET / HTTP/1.1\r\n"
6829 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226830 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136831 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196832 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226833 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6834 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136835 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196836 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136837 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196838 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226839
6840 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416841 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6842 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226843 };
6844
6845 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416846 CreateMockRead(conn_resp1, 1, ASYNC),
6847 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6848 CreateMockRead(wrapped_body1, 4, ASYNC),
6849 CreateMockRead(conn_resp2, 6, ASYNC),
6850 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6851 CreateMockRead(wrapped_body2, 9, ASYNC),
6852 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226853 };
6854
Ryan Sleevib8d7ea02018-05-07 20:01:016855 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506856 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226857
6858 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366859 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506860 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226861 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506862 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226863 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506864 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226865
6866 TestCompletionCallback callback;
6867
bnc691fda62016-08-12 00:43:166868 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206869 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016870 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226871
6872 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166873 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226874 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6875
bnc691fda62016-08-12 00:43:166876 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526877 ASSERT_TRUE(response);
6878 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226879 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6880
6881 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446882 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166883 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506884 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226885
bnc691fda62016-08-12 00:43:166886 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206887 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016888 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226889
6890 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166891 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226892 // Even though the SPDY connection is reused, a new tunnelled connection has
6893 // to be created, so the socket's load timing looks like a fresh connection.
6894 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6895
6896 // The requests should have different IDs, since they each are using their own
6897 // separate stream.
6898 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6899
bnc691fda62016-08-12 00:43:166900 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506901 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226902}
6903
6904// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6905// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016906TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226907 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6908 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566909 session_deps_.proxy_resolution_service =
6910 ConfiguredProxyResolutionService::CreateFixed(
6911 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146912 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076913 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096914 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506915 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226916
6917 HttpRequestInfo request1;
6918 request1.method = "GET";
bncce36dca22015-04-21 22:11:236919 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226920 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106921 request1.traffic_annotation =
6922 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226923
6924 HttpRequestInfo request2;
6925 request2.method = "GET";
bncce36dca22015-04-21 22:11:236926 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226927 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106928 request2.traffic_annotation =
6929 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226930
bncce36dca22015-04-21 22:11:236931 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136932 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046933 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6934 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136935 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356936 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226937
bncce36dca22015-04-21 22:11:236938 // Fetch https://www.example.org/ via HTTP.
6939 const char get1[] =
6940 "GET / HTTP/1.1\r\n"
6941 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226942 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136943 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196944 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226945 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6946 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136947 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196948 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136949 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196950 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136951 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416952 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226953
bncce36dca22015-04-21 22:11:236954 // Fetch https://www.example.org/2 via HTTP.
6955 const char get2[] =
6956 "GET /2 HTTP/1.1\r\n"
6957 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226958 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136959 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196960 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226961 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6962 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136963 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196964 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136965 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196966 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226967
6968 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416969 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6970 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226971 };
6972
6973 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416974 CreateMockRead(conn_resp1, 1, ASYNC),
6975 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466976 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416977 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466978 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416979 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226980 };
6981
Ryan Sleevib8d7ea02018-05-07 20:01:016982 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506983 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226984
6985 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366986 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226988 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226990
6991 TestCompletionCallback callback;
6992
bnc87dcefc2017-05-25 12:47:586993 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196994 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206995 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016996 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226997
6998 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016999 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227000
7001 LoadTimingInfo load_timing_info;
7002 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7003 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7004
7005 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527006 ASSERT_TRUE(response);
7007 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227008 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7009
7010 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447011 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:507012 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227013 trans.reset();
7014
bnc87dcefc2017-05-25 12:47:587015 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:197016 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207017 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227019
[email protected]f6c63db52013-02-02 00:35:227020 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017021 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227022
7023 LoadTimingInfo load_timing_info2;
7024 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
7025 TestLoadTimingReused(load_timing_info2);
7026
7027 // The requests should have the same ID.
7028 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7029
[email protected]90499482013-06-01 00:39:507030 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227031}
7032
7033// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
7034// Proxy to different servers.
bncd16676a2016-07-20 16:23:017035TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:227036 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567037 session_deps_.proxy_resolution_service =
7038 ConfiguredProxyResolutionService::CreateFixed(
7039 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147040 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077041 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097042 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507043 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227044
7045 HttpRequestInfo request1;
7046 request1.method = "GET";
bncce36dca22015-04-21 22:11:237047 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227048 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107049 request1.traffic_annotation =
7050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227051
7052 HttpRequestInfo request2;
7053 request2.method = "GET";
bncce36dca22015-04-21 22:11:237054 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227055 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:107056 request2.traffic_annotation =
7057 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227058
bncce36dca22015-04-21 22:11:237059 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137060 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:237061 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137062 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:157063 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137064 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:357065 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:137066 spdy::SpdySerializedFrame body1(
7067 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:387068 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:227069
bncce36dca22015-04-21 22:11:237070 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137071 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:237072 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137073 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:157074 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137075 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357076 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137077 spdy::SpdySerializedFrame body2(
7078 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227079
7080 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417081 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227082 };
7083
7084 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417085 CreateMockRead(get_resp1, 1, ASYNC),
7086 CreateMockRead(body1, 2, ASYNC),
7087 CreateMockRead(get_resp2, 4, ASYNC),
7088 CreateMockRead(body2, 5, ASYNC),
7089 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227090 };
7091
Ryan Sleevib8d7ea02018-05-07 20:01:017092 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507093 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227094
7095 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367096 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227098
7099 TestCompletionCallback callback;
7100
bnc87dcefc2017-05-25 12:47:587101 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197102 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207103 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017104 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227105
7106 LoadTimingInfo load_timing_info;
7107 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7108 TestLoadTimingNotReused(load_timing_info,
7109 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7110
7111 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527112 ASSERT_TRUE(response);
7113 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027114 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227115
7116 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447117 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507118 rv = trans->Read(buf.get(), 256, callback.callback());
7119 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227120 // Delete the first request, so the second one can reuse the socket.
7121 trans.reset();
7122
bnc691fda62016-08-12 00:43:167123 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207124 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017125 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227126
7127 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167128 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227129 TestLoadTimingReused(load_timing_info2);
7130
7131 // The requests should have the same ID.
7132 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7133
bnc691fda62016-08-12 00:43:167134 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507135 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227136}
7137
Matt Menke2436b2f2018-12-11 18:07:117138// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7139// direct (non-proxied) request to the proxy server are not pooled, as that
7140// would break socket pool isolation.
7141TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7142 ProxyConfig proxy_config;
7143 proxy_config.set_auto_detect(true);
7144 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7145
7146 CapturingProxyResolver capturing_proxy_resolver;
7147 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567148 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117149 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7150 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7151 std::make_unique<CapturingProxyResolverFactory>(
7152 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097153 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117154
7155 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7156
7157 SpdyTestUtil spdy_util1;
7158 // CONNECT to www.example.org:443 via HTTP/2.
7159 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047160 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7161 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117162 // fetch https://www.example.org/ via HTTP/2.
7163 const char kMyUrl[] = "https://www.example.org/";
7164 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7165 spdy::SpdySerializedFrame wrapped_get(
7166 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7167 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357168 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117169 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357170 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117171 spdy::SpdySerializedFrame wrapped_get_resp(
7172 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7173 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7174 spdy::SpdySerializedFrame wrapped_body(
7175 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7176 spdy::SpdySerializedFrame window_update_get_resp(
7177 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7178 spdy::SpdySerializedFrame window_update_body(
7179 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7180
7181 MockWrite spdy_writes1[] = {
7182 CreateMockWrite(connect, 0),
7183 CreateMockWrite(wrapped_get, 2),
7184 CreateMockWrite(window_update_get_resp, 6),
7185 CreateMockWrite(window_update_body, 7),
7186 };
7187
7188 MockRead spdy_reads1[] = {
7189 CreateMockRead(conn_resp, 1, ASYNC),
7190 MockRead(ASYNC, ERR_IO_PENDING, 3),
7191 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7192 CreateMockRead(wrapped_body, 5, ASYNC),
7193 MockRead(ASYNC, 0, 8),
7194 };
7195
7196 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7197 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7198
7199 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7200 // a new pipe.
7201 SpdyTestUtil spdy_util2;
7202 spdy::SpdySerializedFrame req(
7203 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7204 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7205
7206 spdy::SpdySerializedFrame resp(
7207 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7208 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7209 MockRead spdy_reads2[] = {
7210 CreateMockRead(resp, 1),
7211 CreateMockRead(data, 2),
7212 MockRead(ASYNC, 0, 3),
7213 };
7214 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7215 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7216
7217 SSLSocketDataProvider ssl(ASYNC, OK);
7218 ssl.next_proto = kProtoHTTP2;
7219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7220 SSLSocketDataProvider ssl2(ASYNC, OK);
7221 ssl2.next_proto = kProtoHTTP2;
7222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7223 SSLSocketDataProvider ssl3(ASYNC, OK);
7224 ssl3.next_proto = kProtoHTTP2;
7225 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7226
7227 TestCompletionCallback callback;
7228 std::string response_data;
7229
7230 // Make a request using proxy:70 as a HTTP/2 proxy.
7231 capturing_proxy_resolver.set_proxy_server(
7232 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7233 HttpRequestInfo request1;
7234 request1.method = "GET";
7235 request1.url = GURL("https://www.example.org/");
7236 request1.traffic_annotation =
7237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7238
7239 HttpNetworkTransaction trans1(LOWEST, session.get());
7240 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7241 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7242
7243 // Allow the SpdyProxyClientSocket's write callback to complete.
7244 base::RunLoop().RunUntilIdle();
7245 // Now allow the read of the response to complete.
7246 spdy_data1.Resume();
7247 rv = callback.WaitForResult();
7248 EXPECT_THAT(rv, IsOk());
7249
7250 const HttpResponseInfo* response = trans1.GetResponseInfo();
7251 ASSERT_TRUE(response);
7252 ASSERT_TRUE(response->headers);
7253 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7254
7255 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7256 EXPECT_EQ(kUploadData, response_data);
7257 RunUntilIdle();
7258
7259 // Make a direct HTTP/2 request to proxy:70.
7260 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7261 HttpRequestInfo request2;
7262 request2.method = "GET";
7263 request2.url = GURL("https://proxy:70/");
7264 request2.traffic_annotation =
7265 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7266 HttpNetworkTransaction trans2(LOWEST, session.get());
7267 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7268 NetLogWithSource())),
7269 IsOk());
7270 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7271}
7272
7273// Same as above, but reverse request order, since the code to check for an
7274// existing session is different for tunnels and direct connections.
7275TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7276 // Configure against https proxy server "myproxy:80".
7277 ProxyConfig proxy_config;
7278 proxy_config.set_auto_detect(true);
7279 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7280
7281 CapturingProxyResolver capturing_proxy_resolver;
7282 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567283 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117284 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7285 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7286 std::make_unique<CapturingProxyResolverFactory>(
7287 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097288 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117289
7290 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7291 // Fetch https://proxy:70/ via HTTP/2.
7292 SpdyTestUtil spdy_util1;
7293 spdy::SpdySerializedFrame req(
7294 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7295 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7296
7297 spdy::SpdySerializedFrame resp(
7298 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7299 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7300 MockRead spdy_reads1[] = {
7301 CreateMockRead(resp, 1),
7302 CreateMockRead(data, 2),
7303 MockRead(ASYNC, 0, 3),
7304 };
7305 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7306 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7307
7308 SpdyTestUtil spdy_util2;
7309 // CONNECT to www.example.org:443 via HTTP/2.
7310 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047311 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7312 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117313 // fetch https://www.example.org/ via HTTP/2.
7314 const char kMyUrl[] = "https://www.example.org/";
7315 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7316 spdy::SpdySerializedFrame wrapped_get(
7317 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7318 spdy::SpdySerializedFrame conn_resp(
7319 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7320 spdy::SpdySerializedFrame get_resp(
7321 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7322 spdy::SpdySerializedFrame wrapped_get_resp(
7323 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7324 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7325 spdy::SpdySerializedFrame wrapped_body(
7326 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7327 spdy::SpdySerializedFrame window_update_get_resp(
7328 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7329 spdy::SpdySerializedFrame window_update_body(
7330 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7331
7332 MockWrite spdy_writes2[] = {
7333 CreateMockWrite(connect, 0),
7334 CreateMockWrite(wrapped_get, 2),
7335 CreateMockWrite(window_update_get_resp, 6),
7336 CreateMockWrite(window_update_body, 7),
7337 };
7338
7339 MockRead spdy_reads2[] = {
7340 CreateMockRead(conn_resp, 1, ASYNC),
7341 MockRead(ASYNC, ERR_IO_PENDING, 3),
7342 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7343 CreateMockRead(wrapped_body, 5, ASYNC),
7344 MockRead(ASYNC, 0, 8),
7345 };
7346
7347 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7348 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7349
7350 SSLSocketDataProvider ssl(ASYNC, OK);
7351 ssl.next_proto = kProtoHTTP2;
7352 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7353 SSLSocketDataProvider ssl2(ASYNC, OK);
7354 ssl2.next_proto = kProtoHTTP2;
7355 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7356 SSLSocketDataProvider ssl3(ASYNC, OK);
7357 ssl3.next_proto = kProtoHTTP2;
7358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7359
7360 TestCompletionCallback callback;
7361 std::string response_data;
7362
7363 // Make a direct HTTP/2 request to proxy:70.
7364 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7365 HttpRequestInfo request1;
7366 request1.method = "GET";
7367 request1.url = GURL("https://proxy:70/");
7368 request1.traffic_annotation =
7369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7370 HttpNetworkTransaction trans1(LOWEST, session.get());
7371 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7372 NetLogWithSource())),
7373 IsOk());
7374 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7375 RunUntilIdle();
7376
7377 // Make a request using proxy:70 as a HTTP/2 proxy.
7378 capturing_proxy_resolver.set_proxy_server(
7379 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7380 HttpRequestInfo request2;
7381 request2.method = "GET";
7382 request2.url = GURL("https://www.example.org/");
7383 request2.traffic_annotation =
7384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7385
7386 HttpNetworkTransaction trans2(LOWEST, session.get());
7387 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7388 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7389
7390 // Allow the SpdyProxyClientSocket's write callback to complete.
7391 base::RunLoop().RunUntilIdle();
7392 // Now allow the read of the response to complete.
7393 spdy_data2.Resume();
7394 rv = callback.WaitForResult();
7395 EXPECT_THAT(rv, IsOk());
7396
7397 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7398 ASSERT_TRUE(response2);
7399 ASSERT_TRUE(response2->headers);
7400 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7401
7402 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7403 EXPECT_EQ(kUploadData, response_data);
7404}
7405
[email protected]2df19bb2010-08-25 20:13:467406// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017407TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467408 HttpRequestInfo request;
7409 request.method = "GET";
bncce36dca22015-04-21 22:11:237410 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467411 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297412 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:107413 request.traffic_annotation =
7414 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467415
[email protected]79cb5c12011-09-12 13:12:047416 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567417 session_deps_.proxy_resolution_service =
7418 ConfiguredProxyResolutionService::CreateFixed(
7419 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147420 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077421 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277423
[email protected]2df19bb2010-08-25 20:13:467424 // Since we have proxy, should use full url
7425 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167426 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7427 "Host: www.example.org\r\n"
7428 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467429
bnc691fda62016-08-12 00:43:167430 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237431 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167432 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7433 "Host: www.example.org\r\n"
7434 "Proxy-Connection: keep-alive\r\n"
7435 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467436 };
7437
7438 // The proxy responds to the GET with a 407, using a persistent
7439 // connection.
7440 MockRead data_reads1[] = {
7441 // No credentials.
7442 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7443 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7444 MockRead("Proxy-Connection: keep-alive\r\n"),
7445 MockRead("Content-Length: 0\r\n\r\n"),
7446
7447 MockRead("HTTP/1.1 200 OK\r\n"),
7448 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7449 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067450 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467451 };
7452
Ryan Sleevib8d7ea02018-05-07 20:01:017453 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077454 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067455 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077456 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467457
[email protected]49639fa2011-12-20 23:22:417458 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467459
bnc691fda62016-08-12 00:43:167460 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507461
bnc691fda62016-08-12 00:43:167462 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467464
7465 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017466 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467467
[email protected]58e32bb2013-01-21 18:23:257468 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167469 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257470 TestLoadTimingNotReused(load_timing_info,
7471 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7472
bnc691fda62016-08-12 00:43:167473 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527474 ASSERT_TRUE(response);
7475 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467476 EXPECT_EQ(407, response->headers->response_code());
7477 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587478 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507479 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467480
[email protected]49639fa2011-12-20 23:22:417481 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467482
bnc691fda62016-08-12 00:43:167483 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017484 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467485
7486 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017487 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467488
[email protected]58e32bb2013-01-21 18:23:257489 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167490 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257491 // Retrying with HTTP AUTH is considered to be reusing a socket.
7492 TestLoadTimingReused(load_timing_info);
7493
bnc691fda62016-08-12 00:43:167494 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527495 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467496
7497 EXPECT_TRUE(response->headers->IsKeepAlive());
7498 EXPECT_EQ(200, response->headers->response_code());
7499 EXPECT_EQ(100, response->headers->GetContentLength());
7500 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507501 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467502
7503 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587504 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467505}
7506
[email protected]23e482282013-06-14 16:08:027507void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087508 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427509 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087510 request.method = "GET";
bncce36dca22015-04-21 22:11:237511 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107512 request.traffic_annotation =
7513 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087514
[email protected]cb9bf6ca2011-01-28 13:15:277515 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567516 session_deps_.proxy_resolution_service =
7517 ConfiguredProxyResolutionService::CreateFixed(
7518 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277520
[email protected]c744cf22009-02-27 07:28:087521 // Since we have proxy, should try to establish tunnel.
7522 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177523 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7524 "Host: www.example.org:443\r\n"
7525 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087526 };
7527
7528 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237529 status, MockRead("Content-Length: 10\r\n\r\n"),
7530 // No response body because the test stops reading here.
7531 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087532 };
7533
Ryan Sleevib8d7ea02018-05-07 20:01:017534 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077535 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087536
[email protected]49639fa2011-12-20 23:22:417537 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087538
bnc691fda62016-08-12 00:43:167539 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507540
tfarina42834112016-09-22 13:38:207541 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017542 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087543
7544 rv = callback.WaitForResult();
7545 EXPECT_EQ(expected_status, rv);
7546}
7547
[email protected]23e482282013-06-14 16:08:027548void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237549 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087550 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427551 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087552}
7553
bncd16676a2016-07-20 16:23:017554TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087555 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7556}
7557
bncd16676a2016-07-20 16:23:017558TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087559 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7560}
7561
bncd16676a2016-07-20 16:23:017562TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087563 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7564}
7565
bncd16676a2016-07-20 16:23:017566TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087567 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7568}
7569
bncd16676a2016-07-20 16:23:017570TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087571 ConnectStatusHelper(
7572 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7573}
7574
bncd16676a2016-07-20 16:23:017575TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087576 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7577}
7578
bncd16676a2016-07-20 16:23:017579TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087580 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7581}
7582
bncd16676a2016-07-20 16:23:017583TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087584 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7585}
7586
bncd16676a2016-07-20 16:23:017587TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087588 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7589}
7590
bncd16676a2016-07-20 16:23:017591TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087592 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7593}
7594
bncd16676a2016-07-20 16:23:017595TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087596 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7597}
7598
bncd16676a2016-07-20 16:23:017599TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087600 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7601}
7602
bncd16676a2016-07-20 16:23:017603TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087604 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7605}
7606
bncd16676a2016-07-20 16:23:017607TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087608 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7609}
7610
bncd16676a2016-07-20 16:23:017611TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087612 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7613}
7614
bncd16676a2016-07-20 16:23:017615TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087616 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7617}
7618
bncd16676a2016-07-20 16:23:017619TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377620 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7621}
7622
bncd16676a2016-07-20 16:23:017623TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087624 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7625}
7626
bncd16676a2016-07-20 16:23:017627TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087628 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7629}
7630
bncd16676a2016-07-20 16:23:017631TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087632 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7633}
7634
bncd16676a2016-07-20 16:23:017635TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087636 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7637}
7638
bncd16676a2016-07-20 16:23:017639TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087640 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7641}
7642
bncd16676a2016-07-20 16:23:017643TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087644 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7645}
7646
bncd16676a2016-07-20 16:23:017647TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087648 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7649}
7650
bncd16676a2016-07-20 16:23:017651TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087652 ConnectStatusHelperWithExpectedStatus(
7653 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547654 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087655}
7656
bncd16676a2016-07-20 16:23:017657TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087658 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7659}
7660
bncd16676a2016-07-20 16:23:017661TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087662 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7663}
7664
bncd16676a2016-07-20 16:23:017665TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087666 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7667}
7668
bncd16676a2016-07-20 16:23:017669TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087670 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7671}
7672
bncd16676a2016-07-20 16:23:017673TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087674 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7675}
7676
bncd16676a2016-07-20 16:23:017677TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087678 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7679}
7680
bncd16676a2016-07-20 16:23:017681TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087682 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7683}
7684
bncd16676a2016-07-20 16:23:017685TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087686 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7687}
7688
bncd16676a2016-07-20 16:23:017689TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087690 ConnectStatusHelper(
7691 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7692}
7693
bncd16676a2016-07-20 16:23:017694TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087695 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7696}
7697
bncd16676a2016-07-20 16:23:017698TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087699 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7700}
7701
bncd16676a2016-07-20 16:23:017702TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087703 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7704}
7705
bncd16676a2016-07-20 16:23:017706TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087707 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7708}
7709
bncd16676a2016-07-20 16:23:017710TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087711 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7712}
7713
bncd16676a2016-07-20 16:23:017714TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087715 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7716}
7717
bncd16676a2016-07-20 16:23:017718TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087719 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7720}
7721
[email protected]038e9a32008-10-08 22:40:167722// Test the flow when both the proxy server AND origin server require
7723// authentication. Again, this uses basic auth for both since that is
7724// the simplest to mock.
bncd16676a2016-07-20 16:23:017725TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277726 HttpRequestInfo request;
7727 request.method = "GET";
bncce36dca22015-04-21 22:11:237728 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107729 request.traffic_annotation =
7730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277731
[email protected]038e9a32008-10-08 22:40:167732 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567733 session_deps_.proxy_resolution_service =
7734 ConfiguredProxyResolutionService::CreateFixed(
7735 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097736 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077737
bnc691fda62016-08-12 00:43:167738 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167739
[email protected]f9ee6b52008-11-08 06:46:237740 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237741 MockWrite(
7742 "GET http://www.example.org/ HTTP/1.1\r\n"
7743 "Host: www.example.org\r\n"
7744 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237745 };
7746
[email protected]038e9a32008-10-08 22:40:167747 MockRead data_reads1[] = {
7748 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7749 // Give a couple authenticate options (only the middle one is actually
7750 // supported).
[email protected]22927ad2009-09-21 19:56:197751 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167752 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7753 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7755 // Large content-length -- won't matter, as connection will be reset.
7756 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067757 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167758 };
7759
bnc691fda62016-08-12 00:43:167760 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167761 // request we should be issuing -- the final header line contains the
7762 // proxy's credentials.
7763 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237764 MockWrite(
7765 "GET http://www.example.org/ HTTP/1.1\r\n"
7766 "Host: www.example.org\r\n"
7767 "Proxy-Connection: keep-alive\r\n"
7768 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167769 };
7770
7771 // Now the proxy server lets the request pass through to origin server.
7772 // The origin server responds with a 401.
7773 MockRead data_reads2[] = {
7774 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7775 // Note: We are using the same realm-name as the proxy server. This is
7776 // completely valid, as realms are unique across hosts.
7777 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7779 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067780 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167781 };
7782
bnc691fda62016-08-12 00:43:167783 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167784 // the credentials for both the proxy and origin server.
7785 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237786 MockWrite(
7787 "GET http://www.example.org/ HTTP/1.1\r\n"
7788 "Host: www.example.org\r\n"
7789 "Proxy-Connection: keep-alive\r\n"
7790 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7791 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167792 };
7793
7794 // Lastly we get the desired content.
7795 MockRead data_reads3[] = {
7796 MockRead("HTTP/1.0 200 OK\r\n"),
7797 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7798 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067799 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167800 };
7801
Ryan Sleevib8d7ea02018-05-07 20:01:017802 StaticSocketDataProvider data1(data_reads1, data_writes1);
7803 StaticSocketDataProvider data2(data_reads2, data_writes2);
7804 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077805 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7807 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167808
[email protected]49639fa2011-12-20 23:22:417809 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167810
tfarina42834112016-09-22 13:38:207811 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017812 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167813
7814 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017815 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167816
bnc691fda62016-08-12 00:43:167817 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527818 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587819 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167820
[email protected]49639fa2011-12-20 23:22:417821 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167822
bnc691fda62016-08-12 00:43:167823 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017824 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167825
7826 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017827 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167828
bnc691fda62016-08-12 00:43:167829 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527830 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587831 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167832
[email protected]49639fa2011-12-20 23:22:417833 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167834
bnc691fda62016-08-12 00:43:167835 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7836 callback3.callback());
robpercival214763f2016-07-01 23:27:017837 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167838
7839 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017840 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167841
bnc691fda62016-08-12 00:43:167842 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587843 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167844 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167845}
[email protected]4ddaf2502008-10-23 18:26:197846
[email protected]ea9dc9a2009-09-05 00:43:327847// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7848// can't hook into its internals to cause it to generate predictable NTLM
7849// authorization headers.
7850#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377851// The NTLM authentication unit tests are based on known test data from the
7852// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7853// flow rather than the implementation of the NTLM protocol. See net/ntlm
7854// for the implementation and testing of the protocol.
7855//
7856// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297857
7858// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557859TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427860 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247861 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557862 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107863 request.traffic_annotation =
7864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547865
7866 // Ensure load is not disrupted by flags which suppress behaviour specific
7867 // to other auth schemes.
7868 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247869
Asanka Herathbf0b55d2019-12-07 03:27:097870 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:097871 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097872 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277873
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377874 // Generate the NTLM messages based on known test data.
7875 std::string negotiate_msg;
7876 std::string challenge_msg;
7877 std::string authenticate_msg;
7878 base::Base64Encode(
7879 base::StringPiece(
7880 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247881 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377882 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557883 base::Base64Encode(
7884 base::StringPiece(
7885 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247886 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557887 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377888 base::Base64Encode(
7889 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097890 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557891 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247892 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557893 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377894 &authenticate_msg);
7895
[email protected]3f918782009-02-28 01:29:247896 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557897 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7898 "Host: server\r\n"
7899 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247900 };
7901
7902 MockRead data_reads1[] = {
7903 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047904 // Negotiate and NTLM are often requested together. However, we only want
7905 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7906 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247907 MockRead("WWW-Authenticate: NTLM\r\n"),
7908 MockRead("Connection: close\r\n"),
7909 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367910 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247911 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247912 };
7913
7914 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167915 // After restarting with a null identity, this is the
7916 // request we should be issuing -- the final header line contains a Type
7917 // 1 message.
7918 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557919 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167920 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377921 "Authorization: NTLM "),
7922 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247923
bnc691fda62016-08-12 00:43:167924 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377925 // (using correct credentials). The second request continues on the
7926 // same connection.
bnc691fda62016-08-12 00:43:167927 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557928 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167929 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377930 "Authorization: NTLM "),
7931 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247932 };
7933
7934 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027935 // The origin server responds with a Type 2 message.
7936 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377937 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7938 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027939 MockRead("Content-Type: text/html\r\n\r\n"),
7940 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247941
Bence Béky1e4ef192017-09-18 19:58:027942 // Lastly we get the desired content.
7943 MockRead("HTTP/1.1 200 OK\r\n"),
7944 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7945 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247946 };
7947
Ryan Sleevib8d7ea02018-05-07 20:01:017948 StaticSocketDataProvider data1(data_reads1, data_writes1);
7949 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077950 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7951 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247952
Bence Béky83eb3512017-09-05 12:56:097953 SSLSocketDataProvider ssl1(ASYNC, OK);
7954 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7955 SSLSocketDataProvider ssl2(ASYNC, OK);
7956 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7957
[email protected]49639fa2011-12-20 23:22:417958 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247959
bnc691fda62016-08-12 00:43:167960 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507961
tfarina42834112016-09-22 13:38:207962 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247964
7965 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017966 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247967
bnc691fda62016-08-12 00:43:167968 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227969
bnc691fda62016-08-12 00:43:167970 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527971 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587972 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247973
[email protected]49639fa2011-12-20 23:22:417974 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257975
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377976 rv = trans.RestartWithAuth(
7977 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7978 callback2.callback());
robpercival214763f2016-07-01 23:27:017979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257980
7981 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017982 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257983
bnc691fda62016-08-12 00:43:167984 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257985
bnc691fda62016-08-12 00:43:167986 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527987 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587988 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257989
[email protected]49639fa2011-12-20 23:22:417990 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247991
bnc691fda62016-08-12 00:43:167992 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017993 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247994
[email protected]0757e7702009-03-27 04:00:227995 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017996 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247997
bnc691fda62016-08-12 00:43:167998 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527999 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588000 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028001 EXPECT_EQ(14, response->headers->GetContentLength());
8002
8003 std::string response_data;
8004 rv = ReadTransaction(&trans, &response_data);
8005 EXPECT_THAT(rv, IsOk());
8006 EXPECT_EQ("Please Login\r\n", response_data);
8007
8008 EXPECT_TRUE(data1.AllReadDataConsumed());
8009 EXPECT_TRUE(data1.AllWriteDataConsumed());
8010 EXPECT_TRUE(data2.AllReadDataConsumed());
8011 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:248012}
8013
[email protected]385a4672009-03-11 22:21:298014// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558015TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:428016 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:298017 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558018 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:108019 request.traffic_annotation =
8020 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:298021
Asanka Herathbf0b55d2019-12-07 03:27:098022 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098023 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098024 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278025
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378026 // Generate the NTLM messages based on known test data.
8027 std::string negotiate_msg;
8028 std::string challenge_msg;
8029 std::string authenticate_msg;
8030 base::Base64Encode(
8031 base::StringPiece(
8032 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248033 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378034 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558035 base::Base64Encode(
8036 base::StringPiece(
8037 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248038 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558039 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378040 base::Base64Encode(
8041 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098042 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558043 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248044 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558045 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378046 &authenticate_msg);
8047
8048 // The authenticate message when |kWrongPassword| is sent.
8049 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558050 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
8051 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
8052 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
8053 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
8054 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
8055 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378056
Zentaro Kavanagh1890a3d2018-01-29 19:52:558057 // Sanity check that it's the same length as the correct authenticate message
8058 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378059 ASSERT_EQ(authenticate_msg.length(),
8060 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:558061 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378062
[email protected]385a4672009-03-11 22:21:298063 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558064 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8065 "Host: server\r\n"
8066 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298067 };
8068
8069 MockRead data_reads1[] = {
8070 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048071 // Negotiate and NTLM are often requested together. However, we only want
8072 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8073 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:298074 MockRead("WWW-Authenticate: NTLM\r\n"),
8075 MockRead("Connection: close\r\n"),
8076 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368077 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298078 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298079 };
8080
8081 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168082 // After restarting with a null identity, this is the
8083 // request we should be issuing -- the final header line contains a Type
8084 // 1 message.
8085 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558086 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168087 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378088 "Authorization: NTLM "),
8089 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298090
bnc691fda62016-08-12 00:43:168091 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378092 // (using incorrect credentials). The second request continues on the
8093 // same connection.
bnc691fda62016-08-12 00:43:168094 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558095 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168096 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378097 "Authorization: NTLM "),
8098 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298099 };
8100
8101 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378102 // The origin server responds with a Type 2 message.
8103 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8104 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8105 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8106 MockRead("Content-Type: text/html\r\n\r\n"),
8107 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298108
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378109 // Wrong password.
8110 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8111 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8112 MockRead("Content-Length: 42\r\n"),
8113 MockRead("Content-Type: text/html\r\n\r\n"),
8114 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298115 };
8116
8117 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168118 // After restarting with a null identity, this is the
8119 // request we should be issuing -- the final header line contains a Type
8120 // 1 message.
8121 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558122 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168123 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378124 "Authorization: NTLM "),
8125 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298126
bnc691fda62016-08-12 00:43:168127 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8128 // (the credentials for the origin server). The second request continues
8129 // on the same connection.
8130 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558131 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168132 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378133 "Authorization: NTLM "),
8134 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298135 };
8136
8137 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028138 // The origin server responds with a Type 2 message.
8139 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378140 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8141 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028142 MockRead("Content-Type: text/html\r\n\r\n"),
8143 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298144
Bence Béky1e4ef192017-09-18 19:58:028145 // Lastly we get the desired content.
8146 MockRead("HTTP/1.1 200 OK\r\n"),
8147 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8148 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298149 };
8150
Ryan Sleevib8d7ea02018-05-07 20:01:018151 StaticSocketDataProvider data1(data_reads1, data_writes1);
8152 StaticSocketDataProvider data2(data_reads2, data_writes2);
8153 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078154 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8155 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8156 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298157
Bence Béky83eb3512017-09-05 12:56:098158 SSLSocketDataProvider ssl1(ASYNC, OK);
8159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8160 SSLSocketDataProvider ssl2(ASYNC, OK);
8161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8162 SSLSocketDataProvider ssl3(ASYNC, OK);
8163 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8164
[email protected]49639fa2011-12-20 23:22:418165 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298166
bnc691fda62016-08-12 00:43:168167 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508168
tfarina42834112016-09-22 13:38:208169 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018170 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298171
8172 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018173 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298174
bnc691fda62016-08-12 00:43:168175 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298176
bnc691fda62016-08-12 00:43:168177 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528178 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588179 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298180
[email protected]49639fa2011-12-20 23:22:418181 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298182
[email protected]0757e7702009-03-27 04:00:228183 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378184 rv = trans.RestartWithAuth(
8185 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8186 callback2.callback());
robpercival214763f2016-07-01 23:27:018187 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298188
[email protected]10af5fe72011-01-31 16:17:258189 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018190 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298191
bnc691fda62016-08-12 00:43:168192 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418193 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168194 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018195 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258196 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018197 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168198 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228199
bnc691fda62016-08-12 00:43:168200 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528201 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588202 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228203
[email protected]49639fa2011-12-20 23:22:418204 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228205
8206 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378207 rv = trans.RestartWithAuth(
8208 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8209 callback4.callback());
robpercival214763f2016-07-01 23:27:018210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258211
8212 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018213 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258214
bnc691fda62016-08-12 00:43:168215 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258216
[email protected]49639fa2011-12-20 23:22:418217 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258218
8219 // One more roundtrip
bnc691fda62016-08-12 00:43:168220 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228222
8223 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018224 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228225
bnc691fda62016-08-12 00:43:168226 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588227 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028228 EXPECT_EQ(14, response->headers->GetContentLength());
8229
8230 std::string response_data;
8231 rv = ReadTransaction(&trans, &response_data);
8232 EXPECT_THAT(rv, IsOk());
8233 EXPECT_EQ("Please Login\r\n", response_data);
8234
8235 EXPECT_TRUE(data1.AllReadDataConsumed());
8236 EXPECT_TRUE(data1.AllWriteDataConsumed());
8237 EXPECT_TRUE(data2.AllReadDataConsumed());
8238 EXPECT_TRUE(data2.AllWriteDataConsumed());
8239 EXPECT_TRUE(data3.AllReadDataConsumed());
8240 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298241}
Bence Béky83eb3512017-09-05 12:56:098242
Bence Béky3238f2e12017-09-22 22:44:498243// Server requests NTLM authentication, which is not supported over HTTP/2.
8244// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098245TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Asanka Herathbf0b55d2019-12-07 03:27:098246 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098247 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098248
Zentaro Kavanagh1890a3d2018-01-29 19:52:558249 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098250
8251 HttpRequestInfo request;
8252 request.method = "GET";
8253 request.url = GURL(kUrl);
Ramin Halavatib5e433e2018-02-07 07:41:108254 request.traffic_annotation =
8255 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098256
8257 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:138258 spdy::SpdyHeaderBlock request_headers0(
8259 spdy_util_.ConstructGetHeaderBlock(kUrl));
8260 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098261 1, std::move(request_headers0), LOWEST, true));
8262
Ryan Hamilton0239aac2018-05-19 00:03:138263 spdy::SpdyHeaderBlock response_headers0;
8264 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098265 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138266 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098267 1, std::move(response_headers0), true));
8268
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378269 // Stream 1 is closed.
8270 spdy_util_.UpdateWithStreamDestruction(1);
8271
8272 // Generate the NTLM messages based on known test data.
8273 std::string negotiate_msg;
8274 std::string challenge_msg;
8275 std::string authenticate_msg;
8276 base::Base64Encode(
8277 base::StringPiece(
8278 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248279 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378280 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558281 base::Base64Encode(
8282 base::StringPiece(
8283 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248284 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558285 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378286 base::Base64Encode(
8287 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098288 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558289 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248290 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558291 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378292 &authenticate_msg);
8293
Bence Béky3238f2e12017-09-22 22:44:498294 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168295 MockRead reads0[] = {CreateMockRead(resp, 1),
8296 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098297
8298 // Retry yet again using HTTP/1.1.
8299 MockWrite writes1[] = {
8300 // After restarting with a null identity, this is the
8301 // request we should be issuing -- the final header line contains a Type
8302 // 1 message.
8303 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558304 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098305 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378306 "Authorization: NTLM "),
8307 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098308
8309 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8310 // (the credentials for the origin server). The second request continues
8311 // on the same connection.
8312 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558313 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098314 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378315 "Authorization: NTLM "),
8316 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098317 };
8318
8319 MockRead reads1[] = {
8320 // The origin server responds with a Type 2 message.
8321 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378322 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8323 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098324 MockRead("Content-Type: text/html\r\n\r\n"),
8325 MockRead("You are not authorized to view this page\r\n"),
8326
8327 // Lastly we get the desired content.
8328 MockRead("HTTP/1.1 200 OK\r\n"),
8329 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028330 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098331 };
Ryan Sleevib8d7ea02018-05-07 20:01:018332 SequencedSocketData data0(reads0, writes0);
8333 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098334 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8335 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8336
8337 SSLSocketDataProvider ssl0(ASYNC, OK);
8338 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168339 ssl0.next_protos_expected_in_ssl_config =
8340 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098341 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168342 // When creating the second connection, only HTTP/1.1 should be allowed.
8343 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098344 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8345 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8346
8347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8349
8350 TestCompletionCallback callback1;
8351 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8352 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8353
8354 rv = callback1.WaitForResult();
8355 EXPECT_THAT(rv, IsOk());
8356
8357 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8358
8359 const HttpResponseInfo* response = trans.GetResponseInfo();
8360 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588361 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098362
8363 TestCompletionCallback callback2;
8364
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378365 rv = trans.RestartWithAuth(
8366 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8367 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098368 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8369
8370 rv = callback2.WaitForResult();
8371 EXPECT_THAT(rv, IsOk());
8372
8373 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8374
8375 response = trans.GetResponseInfo();
8376 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588377 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098378
8379 TestCompletionCallback callback3;
8380
8381 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8383
8384 rv = callback3.WaitForResult();
8385 EXPECT_THAT(rv, IsOk());
8386
8387 response = trans.GetResponseInfo();
8388 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588389 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028390 EXPECT_EQ(14, response->headers->GetContentLength());
8391
8392 std::string response_data;
8393 rv = ReadTransaction(&trans, &response_data);
8394 EXPECT_THAT(rv, IsOk());
8395 EXPECT_EQ("Please Login\r\n", response_data);
8396
8397 EXPECT_TRUE(data0.AllReadDataConsumed());
8398 EXPECT_TRUE(data0.AllWriteDataConsumed());
8399 EXPECT_TRUE(data1.AllReadDataConsumed());
8400 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098401}
David Benjamin5cb91132018-04-06 05:54:498402
Matt Menkef2ee07c2019-08-29 02:10:368403#if BUILDFLAG(ENABLE_WEBSOCKETS)
8404
8405// Variant of above test using WebSockets.
8406TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8407 const GURL kInitialUrl("https://server/");
8408 const GURL kWebSocketUrl("wss://server/");
Asanka Herathbf0b55d2019-12-07 03:27:098409 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Matt Menkef2ee07c2019-08-29 02:10:368410 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8411
8412 // Initial request establishes an H2 connection, which will then be reused for
8413 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8414 // it won't create a new one.
8415 spdy::SpdyHeaderBlock initial_request_headers(
8416 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8417 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8418 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8419 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8420
8421 // Settings frame, indicating WebSockets is supported.
8422 spdy::SettingsMap settings;
8423 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8424 spdy::SpdySerializedFrame settings_frame(
8425 spdy_util_.ConstructSpdySettings(settings));
8426
8427 // Response headers for first request. Body is never received, but that
8428 // shouldn't matter for the purposes of this test.
8429 spdy::SpdySerializedFrame initial_response(
8430 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8431
8432 // First WebSocket request, which has no credentials.
8433 spdy::SpdyHeaderBlock websocket_request_headers;
8434 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8435 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8436 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8437 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8438 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8439 websocket_request_headers["origin"] = "http://server";
8440 websocket_request_headers["sec-websocket-version"] = "13";
8441 websocket_request_headers["sec-websocket-extensions"] =
8442 "permessage-deflate; client_max_window_bits";
8443 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8444 3, std::move(websocket_request_headers), MEDIUM, false));
8445
8446 // Auth challenge to WebSocket request.
8447 spdy::SpdyHeaderBlock auth_challenge_headers;
8448 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8449 auth_challenge_headers["www-authenticate"] = "NTLM";
8450 spdy::SpdySerializedFrame websocket_auth_challenge(
8451 spdy_util_.ConstructSpdyResponseHeaders(
8452 3, std::move(auth_challenge_headers), true));
8453
8454 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8455 CreateMockWrite(settings_ack, 2),
8456 CreateMockWrite(websocket_request, 4),
8457 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8458 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8459 CreateMockRead(initial_response, 3),
8460 CreateMockRead(websocket_auth_challenge, 5),
8461 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8462
8463 // Generate the NTLM messages based on known test data.
8464 std::string negotiate_msg;
8465 std::string challenge_msg;
8466 std::string authenticate_msg;
8467 base::Base64Encode(
8468 base::StringPiece(
8469 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8470 base::size(ntlm::test::kExpectedNegotiateMsg)),
8471 &negotiate_msg);
8472 base::Base64Encode(
8473 base::StringPiece(
8474 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8475 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8476 &challenge_msg);
8477 base::Base64Encode(
8478 base::StringPiece(
8479 reinterpret_cast<const char*>(
8480 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8481 base::size(
8482 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8483 &authenticate_msg);
8484
8485 // Retry yet again using HTTP/1.1.
8486 MockWrite writes1[] = {
8487 // After restarting with a null identity, this is the
8488 // request we should be issuing -- the final header line contains a Type
8489 // 1 message.
8490 MockWrite("GET / HTTP/1.1\r\n"
8491 "Host: server\r\n"
8492 "Connection: Upgrade\r\n"
8493 "Authorization: NTLM "),
8494 MockWrite(negotiate_msg.c_str()),
8495 MockWrite("\r\n"),
8496 MockWrite("Origin: http://server\r\n"
8497 "Sec-WebSocket-Version: 13\r\n"
8498 "Upgrade: websocket\r\n"
8499 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8500 "Sec-WebSocket-Extensions: permessage-deflate; "
8501 "client_max_window_bits\r\n\r\n"),
8502
8503 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8504 // (the credentials for the origin server). The second request continues
8505 // on the same connection.
8506 MockWrite("GET / HTTP/1.1\r\n"
8507 "Host: server\r\n"
8508 "Connection: Upgrade\r\n"
8509 "Authorization: NTLM "),
8510 MockWrite(authenticate_msg.c_str()),
8511 MockWrite("\r\n"),
8512 MockWrite("Origin: http://server\r\n"
8513 "Sec-WebSocket-Version: 13\r\n"
8514 "Upgrade: websocket\r\n"
8515 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8516 "Sec-WebSocket-Extensions: permessage-deflate; "
8517 "client_max_window_bits\r\n\r\n"),
8518 };
8519
8520 MockRead reads1[] = {
8521 // The origin server responds with a Type 2 message.
8522 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8523 MockRead("WWW-Authenticate: NTLM "),
8524 MockRead(challenge_msg.c_str()),
8525 MockRead("\r\n"),
8526 MockRead("Content-Length: 42\r\n"),
8527 MockRead("Content-Type: text/html\r\n\r\n"),
8528 MockRead("You are not authorized to view this page\r\n"),
8529
8530 // Lastly we get the desired content.
8531 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8532 "Upgrade: websocket\r\n"
8533 "Connection: Upgrade\r\n"
8534 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8535 };
8536 SequencedSocketData data0(reads0, writes0);
8537 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8538 SSLSocketDataProvider ssl0(ASYNC, OK);
8539 ssl0.next_proto = kProtoHTTP2;
8540 ssl0.next_protos_expected_in_ssl_config =
8541 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8542 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8543
8544 StaticSocketDataProvider data1(reads1, writes1);
8545 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8546 SSLSocketDataProvider ssl1(ASYNC, OK);
8547 // When creating the second connection, only HTTP/1.1 should be allowed.
8548 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8549 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8550
8551 session_deps_.enable_websocket_over_http2 = true;
8552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8553
8554 HttpRequestInfo initial_request_info;
8555 initial_request_info.method = "GET";
8556 initial_request_info.url = kInitialUrl;
8557 initial_request_info.traffic_annotation =
8558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8559 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8560 TestCompletionCallback initial_callback;
8561 int rv = initial_trans.Start(&initial_request_info,
8562 initial_callback.callback(), NetLogWithSource());
8563 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8564
8565 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8566 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8567
8568 HttpRequestInfo websocket_request_info;
8569 websocket_request_info.method = "GET";
8570 websocket_request_info.url = kWebSocketUrl;
8571 websocket_request_info.traffic_annotation =
8572 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8573 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8574 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8575 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8576 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8577 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8578 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8579 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8580
8581 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8582
8583 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8584 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8585 &websocket_stream_create_helper);
8586
8587 TestCompletionCallback websocket_callback;
8588 rv = websocket_trans.Start(&websocket_request_info,
8589 websocket_callback.callback(), NetLogWithSource());
8590 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8591
8592 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8593
8594 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8595 ASSERT_TRUE(response);
8596 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8597
8598 rv = websocket_trans.RestartWithAuth(
8599 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8600 websocket_callback.callback());
8601 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8602
8603 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8604
8605 response = websocket_trans.GetResponseInfo();
8606 ASSERT_TRUE(response);
8607 EXPECT_FALSE(response->auth_challenge.has_value());
8608
8609 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8610 websocket_callback.callback());
8611 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8612
8613 // The server should have been marked as requiring HTTP/1.1. The important
8614 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8615 // WSS.
8616 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8617 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8618}
8619
8620#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8621
David Benjamin5cb91132018-04-06 05:54:498622// Test that, if we have an NTLM proxy and the origin resets the connection, we
David Benjamin07a07d652020-02-26 22:26:598623// do no retry forever as a result of TLS retries. This is a regression test for
8624// https://crbug.com/823387. The version interference probe has since been
8625// removed, but we now have a legacy crypto fallback. (If that fallback is
8626// removed, this test should be kept but with the expectations tweaked, in case
8627// future fallbacks are added.)
David Benjamin5cb91132018-04-06 05:54:498628TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8629 // The NTLM test data expects the proxy to be named 'server'. The origin is
8630 // https://origin/.
8631 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:568632 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
David Benjamin5cb91132018-04-06 05:54:498633 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8634
David Benjamin151ec6b2019-08-02 19:38:528635 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498636 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078637 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498638
8639 HttpRequestInfo request;
8640 request.method = "GET";
8641 request.url = GURL("https://origin/");
8642 request.traffic_annotation =
8643 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8644
8645 // Ensure load is not disrupted by flags which suppress behaviour specific
8646 // to other auth schemes.
8647 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8648
Asanka Herathbf0b55d2019-12-07 03:27:098649 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
David Benjamin5cb91132018-04-06 05:54:498650 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8651 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8652
8653 // Generate the NTLM messages based on known test data.
8654 std::string negotiate_msg;
8655 std::string challenge_msg;
8656 std::string authenticate_msg;
8657 base::Base64Encode(
8658 base::StringPiece(
8659 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248660 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498661 &negotiate_msg);
8662 base::Base64Encode(
8663 base::StringPiece(
8664 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248665 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498666 &challenge_msg);
8667 base::Base64Encode(
8668 base::StringPiece(
8669 reinterpret_cast<const char*>(
8670 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248671 base::size(
David Benjamin5cb91132018-04-06 05:54:498672 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8673 &authenticate_msg);
8674
8675 MockWrite data_writes[] = {
8676 // The initial CONNECT request.
8677 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8678 "Host: origin:443\r\n"
8679 "Proxy-Connection: keep-alive\r\n\r\n"),
8680
8681 // After restarting with an identity.
8682 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8683 "Host: origin:443\r\n"
8684 "Proxy-Connection: keep-alive\r\n"
8685 "Proxy-Authorization: NTLM "),
8686 MockWrite(negotiate_msg.c_str()),
8687 // End headers.
8688 MockWrite("\r\n\r\n"),
8689
8690 // The second restart.
8691 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8692 "Host: origin:443\r\n"
8693 "Proxy-Connection: keep-alive\r\n"
8694 "Proxy-Authorization: NTLM "),
8695 MockWrite(authenticate_msg.c_str()),
8696 // End headers.
8697 MockWrite("\r\n\r\n"),
8698 };
8699
8700 MockRead data_reads[] = {
8701 // The initial NTLM response.
8702 MockRead("HTTP/1.1 407 Access Denied\r\n"
8703 "Content-Length: 0\r\n"
8704 "Proxy-Authenticate: NTLM\r\n\r\n"),
8705
8706 // The NTLM challenge message.
8707 MockRead("HTTP/1.1 407 Access Denied\r\n"
8708 "Content-Length: 0\r\n"
8709 "Proxy-Authenticate: NTLM "),
8710 MockRead(challenge_msg.c_str()),
8711 // End headers.
8712 MockRead("\r\n\r\n"),
8713
8714 // Finally the tunnel is established.
8715 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
8716 };
8717
Ryan Sleevib8d7ea02018-05-07 20:01:018718 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:498719 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:498720 session_deps_.socket_factory->AddSocketDataProvider(&data);
8721 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:498722
David Benjamin07a07d652020-02-26 22:26:598723 StaticSocketDataProvider data2(data_reads, data_writes);
8724 SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
8725 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8726 session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);
8727
David Benjamin5cb91132018-04-06 05:54:498728 // Start the transaction. The proxy responds with an NTLM authentication
8729 // request.
8730 TestCompletionCallback callback;
8731 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8732 int rv = callback.GetResult(
8733 trans.Start(&request, callback.callback(), NetLogWithSource()));
8734
8735 EXPECT_THAT(rv, IsOk());
8736 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8737 const HttpResponseInfo* response = trans.GetResponseInfo();
8738 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588739 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:498740
David Benjamind61bd532019-04-23 21:11:378741 // Configure credentials and restart. The proxy responds with the challenge
8742 // message.
David Benjamin5cb91132018-04-06 05:54:498743 rv = callback.GetResult(trans.RestartWithAuth(
8744 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8745 callback.callback()));
8746 EXPECT_THAT(rv, IsOk());
8747 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8748 response = trans.GetResponseInfo();
8749 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588750 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:498751
David Benjamin07a07d652020-02-26 22:26:598752 // Restart once more. The tunnel will be established and the the SSL handshake
8753 // will reset. The fallback will then kick in and restart the process. The
8754 // proxy responds with another NTLM authentiation request, but we don't need
8755 // to provide credentials as the cached ones work.
8756 rv = callback.GetResult(
8757 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8758 EXPECT_THAT(rv, IsOk());
8759 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8760 response = trans.GetResponseInfo();
8761 ASSERT_TRUE(response);
8762 EXPECT_FALSE(response->auth_challenge.has_value());
8763
8764 // The proxy responds with the NTLM challenge message.
8765 rv = callback.GetResult(
8766 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8767 EXPECT_THAT(rv, IsOk());
8768 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8769 response = trans.GetResponseInfo();
8770 ASSERT_TRUE(response);
8771 EXPECT_FALSE(response->auth_challenge.has_value());
8772
8773 // Send the NTLM authenticate message. The tunnel is established and the
8774 // handshake resets again. We should not retry again.
David Benjamin5cb91132018-04-06 05:54:498775 rv = callback.GetResult(
8776 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8777 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
8778}
8779
[email protected]ea9dc9a2009-09-05 00:43:328780#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:298781
[email protected]4ddaf2502008-10-23 18:26:198782// Test reading a server response which has only headers, and no body.
8783// After some maximum number of bytes is consumed, the transaction should
8784// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018785TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428786 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198787 request.method = "GET";
bncce36dca22015-04-21 22:11:238788 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108789 request.traffic_annotation =
8790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198791
danakj1fd259a02016-04-16 03:17:098792 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168793 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278794
[email protected]b75b7b2f2009-10-06 00:54:538795 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438796 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538797 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198798
8799 MockRead data_reads[] = {
8800 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068801 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198802 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068803 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198804 };
Ryan Sleevib8d7ea02018-05-07 20:01:018805 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078806 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198807
[email protected]49639fa2011-12-20 23:22:418808 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198809
tfarina42834112016-09-22 13:38:208810 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198812
8813 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018814 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198815}
[email protected]f4e426b2008-11-05 00:24:498816
8817// Make sure that we don't try to reuse a TCPClientSocket when failing to
8818// establish tunnel.
8819// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018820TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278821 HttpRequestInfo request;
8822 request.method = "GET";
bncce36dca22015-04-21 22:11:238823 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108824 request.traffic_annotation =
8825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278826
[email protected]f4e426b2008-11-05 00:24:498827 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:568828 session_deps_.proxy_resolution_service =
8829 ConfiguredProxyResolutionService::CreateFixed(
8830 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018831
danakj1fd259a02016-04-16 03:17:098832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498833
bnc87dcefc2017-05-25 12:47:588834 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198835 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498836
[email protected]f4e426b2008-11-05 00:24:498837 // Since we have proxy, should try to establish tunnel.
8838 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178839 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8840 "Host: www.example.org:443\r\n"
8841 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498842 };
8843
[email protected]77848d12008-11-14 00:00:228844 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498845 // connection. Usually a proxy would return 501 (not implemented),
8846 // or 200 (tunnel established).
8847 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238848 MockRead("HTTP/1.1 404 Not Found\r\n"),
8849 MockRead("Content-Length: 10\r\n\r\n"),
8850 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498851 };
8852
Ryan Sleevib8d7ea02018-05-07 20:01:018853 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078854 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498855
[email protected]49639fa2011-12-20 23:22:418856 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498857
tfarina42834112016-09-22 13:38:208858 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018859 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498860
8861 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018862 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498863
[email protected]b4404c02009-04-10 16:38:528864 // Empty the current queue. This is necessary because idle sockets are
8865 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558866 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528867
[email protected]f4e426b2008-11-05 00:24:498868 // We now check to make sure the TCPClientSocket was not added back to
8869 // the pool.
[email protected]90499482013-06-01 00:39:508870 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498871 trans.reset();
fdoray92e35a72016-06-10 15:54:558872 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498873 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508874 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498875}
[email protected]372d34a2008-11-05 21:30:518876
[email protected]1b157c02009-04-21 01:55:408877// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018878TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428879 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408880 request.method = "GET";
bncce36dca22015-04-21 22:11:238881 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108882 request.traffic_annotation =
8883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408884
danakj1fd259a02016-04-16 03:17:098885 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278886
bnc691fda62016-08-12 00:43:168887 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278888
[email protected]1b157c02009-04-21 01:55:408889 MockRead data_reads[] = {
8890 // A part of the response body is received with the response headers.
8891 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8892 // The rest of the response body is received in two parts.
8893 MockRead("lo"),
8894 MockRead(" world"),
8895 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068896 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408897 };
8898
Ryan Sleevib8d7ea02018-05-07 20:01:018899 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078900 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408901
[email protected]49639fa2011-12-20 23:22:418902 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408903
tfarina42834112016-09-22 13:38:208904 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408906
8907 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018908 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408909
bnc691fda62016-08-12 00:43:168910 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528911 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408912
wezca1070932016-05-26 20:30:528913 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408914 std::string status_line = response->headers->GetStatusLine();
8915 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8916
[email protected]90499482013-06-01 00:39:508917 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408918
8919 std::string response_data;
bnc691fda62016-08-12 00:43:168920 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018921 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408922 EXPECT_EQ("hello world", response_data);
8923
8924 // Empty the current queue. This is necessary because idle sockets are
8925 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558926 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408927
8928 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508929 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408930}
8931
[email protected]76a505b2010-08-25 06:23:008932// Make sure that we recycle a SSL socket after reading all of the response
8933// body.
bncd16676a2016-07-20 16:23:018934TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008935 HttpRequestInfo request;
8936 request.method = "GET";
bncce36dca22015-04-21 22:11:238937 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108938 request.traffic_annotation =
8939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008940
8941 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238942 MockWrite(
8943 "GET / HTTP/1.1\r\n"
8944 "Host: www.example.org\r\n"
8945 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008946 };
8947
8948 MockRead data_reads[] = {
8949 MockRead("HTTP/1.1 200 OK\r\n"),
8950 MockRead("Content-Length: 11\r\n\r\n"),
8951 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068952 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008953 };
8954
[email protected]8ddf8322012-02-23 18:08:068955 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078956 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008957
Ryan Sleevib8d7ea02018-05-07 20:01:018958 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078959 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008960
[email protected]49639fa2011-12-20 23:22:418961 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008962
danakj1fd259a02016-04-16 03:17:098963 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168964 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008965
tfarina42834112016-09-22 13:38:208966 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008967
robpercival214763f2016-07-01 23:27:018968 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8969 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008970
bnc691fda62016-08-12 00:43:168971 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528972 ASSERT_TRUE(response);
8973 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008974 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8975
[email protected]90499482013-06-01 00:39:508976 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008977
8978 std::string response_data;
bnc691fda62016-08-12 00:43:168979 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018980 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008981 EXPECT_EQ("hello world", response_data);
8982
8983 // Empty the current queue. This is necessary because idle sockets are
8984 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558985 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008986
8987 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238988 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008989}
8990
8991// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8992// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018993TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008994 HttpRequestInfo request;
8995 request.method = "GET";
bncce36dca22015-04-21 22:11:238996 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108997 request.traffic_annotation =
8998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008999
9000 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239001 MockWrite(
9002 "GET / HTTP/1.1\r\n"
9003 "Host: www.example.org\r\n"
9004 "Connection: keep-alive\r\n\r\n"),
9005 MockWrite(
9006 "GET / HTTP/1.1\r\n"
9007 "Host: www.example.org\r\n"
9008 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009009 };
9010
9011 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:429012 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9013 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:009014
[email protected]8ddf8322012-02-23 18:08:069015 SSLSocketDataProvider ssl(ASYNC, OK);
9016 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079017 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:009019
Ryan Sleevib8d7ea02018-05-07 20:01:019020 StaticSocketDataProvider data(data_reads, data_writes);
9021 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079022 session_deps_.socket_factory->AddSocketDataProvider(&data);
9023 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:009024
[email protected]49639fa2011-12-20 23:22:419025 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009026
danakj1fd259a02016-04-16 03:17:099027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:589028 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199029 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009030
tfarina42834112016-09-22 13:38:209031 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009032
robpercival214763f2016-07-01 23:27:019033 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9034 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009035
9036 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529037 ASSERT_TRUE(response);
9038 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009039 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9040
[email protected]90499482013-06-01 00:39:509041 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009042
9043 std::string response_data;
9044 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019045 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009046 EXPECT_EQ("hello world", response_data);
9047
9048 // Empty the current queue. This is necessary because idle sockets are
9049 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559050 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009051
9052 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239053 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009054
9055 // Now start the second transaction, which should reuse the previous socket.
9056
bnc87dcefc2017-05-25 12:47:589057 trans =
Jeremy Roman0579ed62017-08-29 15:56:199058 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009059
tfarina42834112016-09-22 13:38:209060 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009061
robpercival214763f2016-07-01 23:27:019062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9063 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009064
9065 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529066 ASSERT_TRUE(response);
9067 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009068 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9069
[email protected]90499482013-06-01 00:39:509070 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009071
9072 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019073 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009074 EXPECT_EQ("hello world", response_data);
9075
9076 // Empty the current queue. This is necessary because idle sockets are
9077 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559078 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009079
9080 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239081 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009082}
9083
maksim.sisov0adf8592016-07-15 06:25:569084// Grab a socket, use it, and put it back into the pool. Then, make
9085// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019086TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569087 HttpRequestInfo request;
9088 request.method = "GET";
9089 request.url = GURL("http://www.example.org/");
9090 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109091 request.traffic_annotation =
9092 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569093
9094 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9095
bnc691fda62016-08-12 00:43:169096 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569097
9098 MockRead data_reads[] = {
9099 // A part of the response body is received with the response headers.
9100 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9101 // The rest of the response body is received in two parts.
9102 MockRead("lo"), MockRead(" world"),
9103 MockRead("junk"), // Should not be read!!
9104 MockRead(SYNCHRONOUS, OK),
9105 };
9106
Ryan Sleevib8d7ea02018-05-07 20:01:019107 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569108 session_deps_.socket_factory->AddSocketDataProvider(&data);
9109
9110 TestCompletionCallback callback;
9111
tfarina42834112016-09-22 13:38:209112 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569113 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9114
9115 EXPECT_THAT(callback.GetResult(rv), IsOk());
9116
bnc691fda62016-08-12 00:43:169117 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569118 ASSERT_TRUE(response);
9119 EXPECT_TRUE(response->headers);
9120 std::string status_line = response->headers->GetStatusLine();
9121 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9122
9123 // Make memory critical notification and ensure the transaction still has been
9124 // operating right.
9125 base::MemoryPressureListener::NotifyMemoryPressure(
9126 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9127 base::RunLoop().RunUntilIdle();
9128
9129 // Socket should not be flushed as long as it is not idle.
9130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9131
9132 std::string response_data;
bnc691fda62016-08-12 00:43:169133 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569134 EXPECT_THAT(rv, IsOk());
9135 EXPECT_EQ("hello world", response_data);
9136
9137 // Empty the current queue. This is necessary because idle sockets are
9138 // added to the connection pool asynchronously with a PostTask.
9139 base::RunLoop().RunUntilIdle();
9140
9141 // We now check to make sure the socket was added back to the pool.
9142 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9143
9144 // Idle sockets should be flushed now.
9145 base::MemoryPressureListener::NotifyMemoryPressure(
9146 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9147 base::RunLoop().RunUntilIdle();
9148
9149 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9150}
9151
yucliu48f235d2018-01-11 00:59:559152// Disable idle socket closing on memory pressure.
9153// Grab a socket, use it, and put it back into the pool. Then, make
9154// low memory notification and ensure the socket pool is NOT flushed.
9155TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9156 HttpRequestInfo request;
9157 request.method = "GET";
9158 request.url = GURL("http://www.example.org/");
9159 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109160 request.traffic_annotation =
9161 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559162
9163 // Disable idle socket closing on memory pressure.
9164 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9165 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9166
9167 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9168
9169 MockRead data_reads[] = {
9170 // A part of the response body is received with the response headers.
9171 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9172 // The rest of the response body is received in two parts.
9173 MockRead("lo"), MockRead(" world"),
9174 MockRead("junk"), // Should not be read!!
9175 MockRead(SYNCHRONOUS, OK),
9176 };
9177
Ryan Sleevib8d7ea02018-05-07 20:01:019178 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559179 session_deps_.socket_factory->AddSocketDataProvider(&data);
9180
9181 TestCompletionCallback callback;
9182
9183 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9185
9186 EXPECT_THAT(callback.GetResult(rv), IsOk());
9187
9188 const HttpResponseInfo* response = trans.GetResponseInfo();
9189 ASSERT_TRUE(response);
9190 EXPECT_TRUE(response->headers);
9191 std::string status_line = response->headers->GetStatusLine();
9192 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9193
9194 // Make memory critical notification and ensure the transaction still has been
9195 // operating right.
9196 base::MemoryPressureListener::NotifyMemoryPressure(
9197 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9198 base::RunLoop().RunUntilIdle();
9199
9200 // Socket should not be flushed as long as it is not idle.
9201 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9202
9203 std::string response_data;
9204 rv = ReadTransaction(&trans, &response_data);
9205 EXPECT_THAT(rv, IsOk());
9206 EXPECT_EQ("hello world", response_data);
9207
9208 // Empty the current queue. This is necessary because idle sockets are
9209 // added to the connection pool asynchronously with a PostTask.
9210 base::RunLoop().RunUntilIdle();
9211
9212 // We now check to make sure the socket was added back to the pool.
9213 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9214
9215 // Idle sockets should NOT be flushed on moderate memory pressure.
9216 base::MemoryPressureListener::NotifyMemoryPressure(
9217 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9218 base::RunLoop().RunUntilIdle();
9219
9220 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9221
9222 // Idle sockets should NOT be flushed on critical memory pressure.
9223 base::MemoryPressureListener::NotifyMemoryPressure(
9224 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9225 base::RunLoop().RunUntilIdle();
9226
9227 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9228}
9229
maksim.sisov0adf8592016-07-15 06:25:569230// Grab an SSL socket, use it, and put it back into the pool. Then, make
9231// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019232TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569233 HttpRequestInfo request;
9234 request.method = "GET";
9235 request.url = GURL("https://www.example.org/");
9236 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109237 request.traffic_annotation =
9238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569239
9240 MockWrite data_writes[] = {
9241 MockWrite("GET / HTTP/1.1\r\n"
9242 "Host: www.example.org\r\n"
9243 "Connection: keep-alive\r\n\r\n"),
9244 };
9245
9246 MockRead data_reads[] = {
9247 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9248 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9249
9250 SSLSocketDataProvider ssl(ASYNC, OK);
9251 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9252
Ryan Sleevib8d7ea02018-05-07 20:01:019253 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569254 session_deps_.socket_factory->AddSocketDataProvider(&data);
9255
9256 TestCompletionCallback callback;
9257
9258 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169259 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569260
Matt Menke9d5e2c92019-02-05 01:42:239261 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209262 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569263
9264 EXPECT_THAT(callback.GetResult(rv), IsOk());
9265
bnc691fda62016-08-12 00:43:169266 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569267 ASSERT_TRUE(response);
9268 ASSERT_TRUE(response->headers);
9269 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9270
9271 // Make memory critical notification and ensure the transaction still has been
9272 // operating right.
9273 base::MemoryPressureListener::NotifyMemoryPressure(
9274 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9275 base::RunLoop().RunUntilIdle();
9276
Matt Menke9d5e2c92019-02-05 01:42:239277 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569278
9279 std::string response_data;
bnc691fda62016-08-12 00:43:169280 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569281 EXPECT_THAT(rv, IsOk());
9282 EXPECT_EQ("hello world", response_data);
9283
9284 // Empty the current queue. This is necessary because idle sockets are
9285 // added to the connection pool asynchronously with a PostTask.
9286 base::RunLoop().RunUntilIdle();
9287
9288 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239289 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569290
9291 // Make memory notification once again and ensure idle socket is closed.
9292 base::MemoryPressureListener::NotifyMemoryPressure(
9293 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9294 base::RunLoop().RunUntilIdle();
9295
Matt Menke9d5e2c92019-02-05 01:42:239296 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569297}
9298
[email protected]b4404c02009-04-10 16:38:529299// Make sure that we recycle a socket after a zero-length response.
9300// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019301TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429302 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529303 request.method = "GET";
bncce36dca22015-04-21 22:11:239304 request.url = GURL(
9305 "http://www.example.org/csi?v=3&s=web&action=&"
9306 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9307 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9308 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:109309 request.traffic_annotation =
9310 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529311
danakj1fd259a02016-04-16 03:17:099312 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279313
[email protected]b4404c02009-04-10 16:38:529314 MockRead data_reads[] = {
9315 MockRead("HTTP/1.1 204 No Content\r\n"
9316 "Content-Length: 0\r\n"
9317 "Content-Type: text/html\r\n\r\n"),
9318 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069319 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529320 };
9321
Ryan Sleevib8d7ea02018-05-07 20:01:019322 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079323 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529324
mmenkecc2298e2015-12-07 18:20:189325 // Transaction must be created after the MockReads, so it's destroyed before
9326 // them.
bnc691fda62016-08-12 00:43:169327 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189328
[email protected]49639fa2011-12-20 23:22:419329 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529330
tfarina42834112016-09-22 13:38:209331 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019332 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529333
9334 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019335 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529336
bnc691fda62016-08-12 00:43:169337 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529338 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529339
wezca1070932016-05-26 20:30:529340 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529341 std::string status_line = response->headers->GetStatusLine();
9342 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9343
[email protected]90499482013-06-01 00:39:509344 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529345
9346 std::string response_data;
bnc691fda62016-08-12 00:43:169347 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019348 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529349 EXPECT_EQ("", response_data);
9350
9351 // Empty the current queue. This is necessary because idle sockets are
9352 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559353 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529354
9355 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509356 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529357}
9358
bncd16676a2016-07-20 16:23:019359TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099360 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229361 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199362 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229363 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279364
[email protected]1c773ea12009-04-28 19:58:429365 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519366 // Transaction 1: a GET request that succeeds. The socket is recycled
9367 // after use.
9368 request[0].method = "GET";
9369 request[0].url = GURL("http://www.google.com/");
9370 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109371 request[0].traffic_annotation =
9372 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519373 // Transaction 2: a POST request. Reuses the socket kept alive from
9374 // transaction 1. The first attempts fails when writing the POST data.
9375 // This causes the transaction to retry with a new socket. The second
9376 // attempt succeeds.
9377 request[1].method = "POST";
9378 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279379 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519380 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:109381 request[1].traffic_annotation =
9382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519383
danakj1fd259a02016-04-16 03:17:099384 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519385
9386 // The first socket is used for transaction 1 and the first attempt of
9387 // transaction 2.
9388
9389 // The response of transaction 1.
9390 MockRead data_reads1[] = {
9391 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9392 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069393 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519394 };
9395 // The mock write results of transaction 1 and the first attempt of
9396 // transaction 2.
9397 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069398 MockWrite(SYNCHRONOUS, 64), // GET
9399 MockWrite(SYNCHRONOUS, 93), // POST
9400 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519401 };
Ryan Sleevib8d7ea02018-05-07 20:01:019402 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519403
9404 // The second socket is used for the second attempt of transaction 2.
9405
9406 // The response of transaction 2.
9407 MockRead data_reads2[] = {
9408 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9409 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069410 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519411 };
9412 // The mock write results of the second attempt of transaction 2.
9413 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069414 MockWrite(SYNCHRONOUS, 93), // POST
9415 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519416 };
Ryan Sleevib8d7ea02018-05-07 20:01:019417 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519418
[email protected]bb88e1d32013-05-03 23:11:079419 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9420 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519421
thestig9d3bb0c2015-01-24 00:49:519422 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519423 "hello world", "welcome"
9424 };
9425
9426 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169427 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519428
[email protected]49639fa2011-12-20 23:22:419429 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519430
tfarina42834112016-09-22 13:38:209431 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019432 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519433
9434 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019435 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519436
bnc691fda62016-08-12 00:43:169437 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529438 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519439
wezca1070932016-05-26 20:30:529440 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519441 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9442
9443 std::string response_data;
bnc691fda62016-08-12 00:43:169444 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019445 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519446 EXPECT_EQ(kExpectedResponseData[i], response_data);
9447 }
9448}
[email protected]f9ee6b52008-11-08 06:46:239449
9450// Test the request-challenge-retry sequence for basic auth when there is
9451// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169452// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019453TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429454 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239455 request.method = "GET";
bncce36dca22015-04-21 22:11:239456 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419457 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109458 request.traffic_annotation =
9459 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299460
danakj1fd259a02016-04-16 03:17:099461 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169462 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279463
[email protected]a97cca42009-08-14 01:00:299464 // The password contains an escaped character -- for this test to pass it
9465 // will need to be unescaped by HttpNetworkTransaction.
9466 EXPECT_EQ("b%40r", request.url.password());
9467
[email protected]f9ee6b52008-11-08 06:46:239468 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239469 MockWrite(
9470 "GET / HTTP/1.1\r\n"
9471 "Host: www.example.org\r\n"
9472 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239473 };
9474
9475 MockRead data_reads1[] = {
9476 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9477 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9478 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069479 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239480 };
9481
[email protected]2262e3a2012-05-22 16:08:169482 // After the challenge above, the transaction will be restarted using the
9483 // identity from the url (foo, b@r) to answer the challenge.
9484 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239485 MockWrite(
9486 "GET / HTTP/1.1\r\n"
9487 "Host: www.example.org\r\n"
9488 "Connection: keep-alive\r\n"
9489 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169490 };
9491
9492 MockRead data_reads2[] = {
9493 MockRead("HTTP/1.0 200 OK\r\n"),
9494 MockRead("Content-Length: 100\r\n\r\n"),
9495 MockRead(SYNCHRONOUS, OK),
9496 };
9497
Ryan Sleevib8d7ea02018-05-07 20:01:019498 StaticSocketDataProvider data1(data_reads1, data_writes1);
9499 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079500 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9501 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239502
[email protected]49639fa2011-12-20 23:22:419503 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209504 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019505 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239506 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019507 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169508 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169509
9510 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169511 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019512 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169513 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019514 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169515 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229516
bnc691fda62016-08-12 00:43:169517 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529518 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169519
9520 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589521 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169522
9523 EXPECT_EQ(100, response->headers->GetContentLength());
9524
9525 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559526 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169527}
9528
9529// Test the request-challenge-retry sequence for basic auth when there is an
9530// incorrect identity in the URL. The identity from the URL should be used only
9531// once.
bncd16676a2016-07-20 16:23:019532TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169533 HttpRequestInfo request;
9534 request.method = "GET";
9535 // Note: the URL has a username:password in it. The password "baz" is
9536 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239537 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169538
9539 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:109540 request.traffic_annotation =
9541 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169542
danakj1fd259a02016-04-16 03:17:099543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169545
9546 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239547 MockWrite(
9548 "GET / HTTP/1.1\r\n"
9549 "Host: www.example.org\r\n"
9550 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169551 };
9552
9553 MockRead data_reads1[] = {
9554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9556 MockRead("Content-Length: 10\r\n\r\n"),
9557 MockRead(SYNCHRONOUS, ERR_FAILED),
9558 };
9559
9560 // After the challenge above, the transaction will be restarted using the
9561 // identity from the url (foo, baz) to answer the challenge.
9562 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239563 MockWrite(
9564 "GET / HTTP/1.1\r\n"
9565 "Host: www.example.org\r\n"
9566 "Connection: keep-alive\r\n"
9567 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169568 };
9569
9570 MockRead data_reads2[] = {
9571 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9572 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9573 MockRead("Content-Length: 10\r\n\r\n"),
9574 MockRead(SYNCHRONOUS, ERR_FAILED),
9575 };
9576
9577 // After the challenge above, the transaction will be restarted using the
9578 // identity supplied by the user (foo, bar) to answer the challenge.
9579 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239580 MockWrite(
9581 "GET / HTTP/1.1\r\n"
9582 "Host: www.example.org\r\n"
9583 "Connection: keep-alive\r\n"
9584 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169585 };
9586
9587 MockRead data_reads3[] = {
9588 MockRead("HTTP/1.0 200 OK\r\n"),
9589 MockRead("Content-Length: 100\r\n\r\n"),
9590 MockRead(SYNCHRONOUS, OK),
9591 };
9592
Ryan Sleevib8d7ea02018-05-07 20:01:019593 StaticSocketDataProvider data1(data_reads1, data_writes1);
9594 StaticSocketDataProvider data2(data_reads2, data_writes2);
9595 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079596 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9597 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9598 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169599
9600 TestCompletionCallback callback1;
9601
tfarina42834112016-09-22 13:38:209602 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019603 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169604
9605 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019606 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169607
bnc691fda62016-08-12 00:43:169608 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169609 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169610 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169612 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019613 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169614 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169615
bnc691fda62016-08-12 00:43:169616 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529617 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589618 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169619
9620 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169621 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019622 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169623 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019624 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169625 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169626
bnc691fda62016-08-12 00:43:169627 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529628 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169629
9630 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589631 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169632
9633 EXPECT_EQ(100, response->headers->GetContentLength());
9634
[email protected]ea9dc9a2009-09-05 00:43:329635 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559636 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329637}
9638
[email protected]2217aa22013-10-11 03:03:549639
9640// Test the request-challenge-retry sequence for basic auth when there is a
9641// correct identity in the URL, but its use is being suppressed. The identity
9642// from the URL should never be used.
bncd16676a2016-07-20 16:23:019643TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549644 HttpRequestInfo request;
9645 request.method = "GET";
bncce36dca22015-04-21 22:11:239646 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549647 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:109648 request.traffic_annotation =
9649 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549650
danakj1fd259a02016-04-16 03:17:099651 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169652 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549653
9654 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239655 MockWrite(
9656 "GET / HTTP/1.1\r\n"
9657 "Host: www.example.org\r\n"
9658 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549659 };
9660
9661 MockRead data_reads1[] = {
9662 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9663 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9664 MockRead("Content-Length: 10\r\n\r\n"),
9665 MockRead(SYNCHRONOUS, ERR_FAILED),
9666 };
9667
9668 // After the challenge above, the transaction will be restarted using the
9669 // identity supplied by the user, not the one in the URL, to answer the
9670 // challenge.
9671 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239672 MockWrite(
9673 "GET / HTTP/1.1\r\n"
9674 "Host: www.example.org\r\n"
9675 "Connection: keep-alive\r\n"
9676 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549677 };
9678
9679 MockRead data_reads3[] = {
9680 MockRead("HTTP/1.0 200 OK\r\n"),
9681 MockRead("Content-Length: 100\r\n\r\n"),
9682 MockRead(SYNCHRONOUS, OK),
9683 };
9684
Ryan Sleevib8d7ea02018-05-07 20:01:019685 StaticSocketDataProvider data1(data_reads1, data_writes1);
9686 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549687 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9688 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9689
9690 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209691 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019692 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549693 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019694 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169695 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549696
bnc691fda62016-08-12 00:43:169697 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529698 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589699 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:549700
9701 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169702 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019703 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549704 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019705 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169706 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549707
bnc691fda62016-08-12 00:43:169708 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529709 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:549710
9711 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589712 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:549713 EXPECT_EQ(100, response->headers->GetContentLength());
9714
9715 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559716 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:549717}
9718
[email protected]f9ee6b52008-11-08 06:46:239719// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:019720TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:099721 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:239722
9723 // Transaction 1: authenticate (foo, bar) on MyRealm1
9724 {
[email protected]1c773ea12009-04-28 19:58:429725 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239726 request.method = "GET";
bncce36dca22015-04-21 22:11:239727 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:109728 request.traffic_annotation =
9729 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239730
bnc691fda62016-08-12 00:43:169731 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279732
[email protected]f9ee6b52008-11-08 06:46:239733 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239734 MockWrite(
9735 "GET /x/y/z HTTP/1.1\r\n"
9736 "Host: www.example.org\r\n"
9737 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239738 };
9739
9740 MockRead data_reads1[] = {
9741 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9742 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9743 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069744 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239745 };
9746
9747 // Resend with authorization (username=foo, password=bar)
9748 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239749 MockWrite(
9750 "GET /x/y/z HTTP/1.1\r\n"
9751 "Host: www.example.org\r\n"
9752 "Connection: keep-alive\r\n"
9753 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239754 };
9755
9756 // Sever accepts the authorization.
9757 MockRead data_reads2[] = {
9758 MockRead("HTTP/1.0 200 OK\r\n"),
9759 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069760 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239761 };
9762
Ryan Sleevib8d7ea02018-05-07 20:01:019763 StaticSocketDataProvider data1(data_reads1, data_writes1);
9764 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079765 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9766 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239767
[email protected]49639fa2011-12-20 23:22:419768 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239769
tfarina42834112016-09-22 13:38:209770 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239772
9773 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019774 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239775
bnc691fda62016-08-12 00:43:169776 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529777 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589778 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239779
[email protected]49639fa2011-12-20 23:22:419780 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239781
bnc691fda62016-08-12 00:43:169782 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9783 callback2.callback());
robpercival214763f2016-07-01 23:27:019784 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239785
9786 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019787 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239788
bnc691fda62016-08-12 00:43:169789 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529790 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589791 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239792 EXPECT_EQ(100, response->headers->GetContentLength());
9793 }
9794
9795 // ------------------------------------------------------------------------
9796
9797 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9798 {
[email protected]1c773ea12009-04-28 19:58:429799 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239800 request.method = "GET";
9801 // Note that Transaction 1 was at /x/y/z, so this is in the same
9802 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239803 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:109804 request.traffic_annotation =
9805 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239806
bnc691fda62016-08-12 00:43:169807 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279808
[email protected]f9ee6b52008-11-08 06:46:239809 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239810 MockWrite(
9811 "GET /x/y/a/b HTTP/1.1\r\n"
9812 "Host: www.example.org\r\n"
9813 "Connection: keep-alive\r\n"
9814 // Send preemptive authorization for MyRealm1
9815 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239816 };
9817
9818 // The server didn't like the preemptive authorization, and
9819 // challenges us for a different realm (MyRealm2).
9820 MockRead data_reads1[] = {
9821 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9822 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9823 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069824 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239825 };
9826
9827 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9828 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239829 MockWrite(
9830 "GET /x/y/a/b HTTP/1.1\r\n"
9831 "Host: www.example.org\r\n"
9832 "Connection: keep-alive\r\n"
9833 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239834 };
9835
9836 // Sever accepts the authorization.
9837 MockRead data_reads2[] = {
9838 MockRead("HTTP/1.0 200 OK\r\n"),
9839 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069840 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239841 };
9842
Ryan Sleevib8d7ea02018-05-07 20:01:019843 StaticSocketDataProvider data1(data_reads1, data_writes1);
9844 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079845 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9846 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239847
[email protected]49639fa2011-12-20 23:22:419848 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239849
tfarina42834112016-09-22 13:38:209850 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239852
9853 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019854 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239855
bnc691fda62016-08-12 00:43:169856 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529857 ASSERT_TRUE(response);
9858 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049859 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439860 EXPECT_EQ("http://www.example.org",
9861 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049862 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199863 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239864
[email protected]49639fa2011-12-20 23:22:419865 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239866
bnc691fda62016-08-12 00:43:169867 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9868 callback2.callback());
robpercival214763f2016-07-01 23:27:019869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239870
9871 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019872 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239873
bnc691fda62016-08-12 00:43:169874 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529875 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589876 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239877 EXPECT_EQ(100, response->headers->GetContentLength());
9878 }
9879
9880 // ------------------------------------------------------------------------
9881
9882 // Transaction 3: Resend a request in MyRealm's protection space --
9883 // succeed with preemptive authorization.
9884 {
[email protected]1c773ea12009-04-28 19:58:429885 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239886 request.method = "GET";
bncce36dca22015-04-21 22:11:239887 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:109888 request.traffic_annotation =
9889 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239890
bnc691fda62016-08-12 00:43:169891 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279892
[email protected]f9ee6b52008-11-08 06:46:239893 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239894 MockWrite(
9895 "GET /x/y/z2 HTTP/1.1\r\n"
9896 "Host: www.example.org\r\n"
9897 "Connection: keep-alive\r\n"
9898 // The authorization for MyRealm1 gets sent preemptively
9899 // (since the url is in the same protection space)
9900 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239901 };
9902
9903 // Sever accepts the preemptive authorization
9904 MockRead data_reads1[] = {
9905 MockRead("HTTP/1.0 200 OK\r\n"),
9906 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069907 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239908 };
9909
Ryan Sleevib8d7ea02018-05-07 20:01:019910 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079911 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239912
[email protected]49639fa2011-12-20 23:22:419913 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239914
tfarina42834112016-09-22 13:38:209915 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239917
9918 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019919 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239920
bnc691fda62016-08-12 00:43:169921 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529922 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239923
Emily Starkf2c9bbd2019-04-09 17:08:589924 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239925 EXPECT_EQ(100, response->headers->GetContentLength());
9926 }
9927
9928 // ------------------------------------------------------------------------
9929
9930 // Transaction 4: request another URL in MyRealm (however the
9931 // url is not known to belong to the protection space, so no pre-auth).
9932 {
[email protected]1c773ea12009-04-28 19:58:429933 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239934 request.method = "GET";
bncce36dca22015-04-21 22:11:239935 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:109936 request.traffic_annotation =
9937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239938
bnc691fda62016-08-12 00:43:169939 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279940
[email protected]f9ee6b52008-11-08 06:46:239941 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239942 MockWrite(
9943 "GET /x/1 HTTP/1.1\r\n"
9944 "Host: www.example.org\r\n"
9945 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239946 };
9947
9948 MockRead data_reads1[] = {
9949 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9950 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9951 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069952 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239953 };
9954
9955 // Resend with authorization from MyRealm's cache.
9956 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239957 MockWrite(
9958 "GET /x/1 HTTP/1.1\r\n"
9959 "Host: www.example.org\r\n"
9960 "Connection: keep-alive\r\n"
9961 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239962 };
9963
9964 // Sever accepts the authorization.
9965 MockRead data_reads2[] = {
9966 MockRead("HTTP/1.0 200 OK\r\n"),
9967 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069968 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239969 };
9970
Ryan Sleevib8d7ea02018-05-07 20:01:019971 StaticSocketDataProvider data1(data_reads1, data_writes1);
9972 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079973 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9974 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239975
[email protected]49639fa2011-12-20 23:22:419976 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239977
tfarina42834112016-09-22 13:38:209978 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239980
9981 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019982 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239983
bnc691fda62016-08-12 00:43:169984 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419985 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169986 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019987 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229988 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019989 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169990 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229991
bnc691fda62016-08-12 00:43:169992 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529993 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589994 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239995 EXPECT_EQ(100, response->headers->GetContentLength());
9996 }
9997
9998 // ------------------------------------------------------------------------
9999
10000 // Transaction 5: request a URL in MyRealm, but the server rejects the
10001 // cached identity. Should invalidate and re-prompt.
10002 {
[email protected]1c773ea12009-04-28 19:58:4210003 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310004 request.method = "GET";
bncce36dca22015-04-21 22:11:2310005 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:1010006 request.traffic_annotation =
10007 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310008
bnc691fda62016-08-12 00:43:1610009 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710010
[email protected]f9ee6b52008-11-08 06:46:2310011 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310012 MockWrite(
10013 "GET /p/q/t HTTP/1.1\r\n"
10014 "Host: www.example.org\r\n"
10015 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310016 };
10017
10018 MockRead data_reads1[] = {
10019 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10020 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10021 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610022 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310023 };
10024
10025 // Resend with authorization from cache for MyRealm.
10026 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310027 MockWrite(
10028 "GET /p/q/t HTTP/1.1\r\n"
10029 "Host: www.example.org\r\n"
10030 "Connection: keep-alive\r\n"
10031 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310032 };
10033
10034 // Sever rejects the authorization.
10035 MockRead data_reads2[] = {
10036 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10037 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10038 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610039 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310040 };
10041
10042 // At this point we should prompt for new credentials for MyRealm.
10043 // Restart with username=foo3, password=foo4.
10044 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310045 MockWrite(
10046 "GET /p/q/t HTTP/1.1\r\n"
10047 "Host: www.example.org\r\n"
10048 "Connection: keep-alive\r\n"
10049 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310050 };
10051
10052 // Sever accepts the authorization.
10053 MockRead data_reads3[] = {
10054 MockRead("HTTP/1.0 200 OK\r\n"),
10055 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610056 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310057 };
10058
Ryan Sleevib8d7ea02018-05-07 20:01:0110059 StaticSocketDataProvider data1(data_reads1, data_writes1);
10060 StaticSocketDataProvider data2(data_reads2, data_writes2);
10061 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710062 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10063 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10064 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:2310065
[email protected]49639fa2011-12-20 23:22:4110066 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310067
tfarina42834112016-09-22 13:38:2010068 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110069 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310070
10071 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110072 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310073
bnc691fda62016-08-12 00:43:1610074 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110075 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610076 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210078 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110079 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610080 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210081
bnc691fda62016-08-12 00:43:1610082 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210083 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810084 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310085
[email protected]49639fa2011-12-20 23:22:4110086 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:2310087
bnc691fda62016-08-12 00:43:1610088 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
10089 callback3.callback());
robpercival214763f2016-07-01 23:27:0110090 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310091
[email protected]0757e7702009-03-27 04:00:2210092 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110093 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310094
bnc691fda62016-08-12 00:43:1610095 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210096 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810097 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310098 EXPECT_EQ(100, response->headers->GetContentLength());
10099 }
10100}
[email protected]89ceba9a2009-03-21 03:46:0610101
[email protected]3c32c5f2010-05-18 15:18:1210102// Tests that nonce count increments when multiple auth attempts
10103// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110104TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410105 HttpAuthHandlerDigest::Factory* digest_factory =
10106 new HttpAuthHandlerDigest::Factory();
10107 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10108 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10109 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710110 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910111 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210112
10113 // Transaction 1: authenticate (foo, bar) on MyRealm1
10114 {
[email protected]3c32c5f2010-05-18 15:18:1210115 HttpRequestInfo request;
10116 request.method = "GET";
bncce36dca22015-04-21 22:11:2310117 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:1010118 request.traffic_annotation =
10119 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210120
bnc691fda62016-08-12 00:43:1610121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710122
[email protected]3c32c5f2010-05-18 15:18:1210123 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310124 MockWrite(
10125 "GET /x/y/z HTTP/1.1\r\n"
10126 "Host: www.example.org\r\n"
10127 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210128 };
10129
10130 MockRead data_reads1[] = {
10131 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10132 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10133 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610134 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210135 };
10136
10137 // Resend with authorization (username=foo, password=bar)
10138 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310139 MockWrite(
10140 "GET /x/y/z HTTP/1.1\r\n"
10141 "Host: www.example.org\r\n"
10142 "Connection: keep-alive\r\n"
10143 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10144 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10145 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10146 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210147 };
10148
10149 // Sever accepts the authorization.
10150 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810151 MockRead("HTTP/1.0 200 OK\r\n"),
10152 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210153 };
10154
Ryan Sleevib8d7ea02018-05-07 20:01:0110155 StaticSocketDataProvider data1(data_reads1, data_writes1);
10156 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710157 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10158 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210159
[email protected]49639fa2011-12-20 23:22:4110160 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210161
tfarina42834112016-09-22 13:38:2010162 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210164
10165 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110166 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210167
bnc691fda62016-08-12 00:43:1610168 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210169 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810170 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210171
[email protected]49639fa2011-12-20 23:22:4110172 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210173
bnc691fda62016-08-12 00:43:1610174 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10175 callback2.callback());
robpercival214763f2016-07-01 23:27:0110176 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210177
10178 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110179 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210180
bnc691fda62016-08-12 00:43:1610181 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210182 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810183 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210184 }
10185
10186 // ------------------------------------------------------------------------
10187
10188 // Transaction 2: Request another resource in digestive's protection space.
10189 // This will preemptively add an Authorization header which should have an
10190 // "nc" value of 2 (as compared to 1 in the first use.
10191 {
[email protected]3c32c5f2010-05-18 15:18:1210192 HttpRequestInfo request;
10193 request.method = "GET";
10194 // Note that Transaction 1 was at /x/y/z, so this is in the same
10195 // protection space as digest.
bncce36dca22015-04-21 22:11:2310196 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:1010197 request.traffic_annotation =
10198 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210199
bnc691fda62016-08-12 00:43:1610200 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710201
[email protected]3c32c5f2010-05-18 15:18:1210202 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310203 MockWrite(
10204 "GET /x/y/a/b HTTP/1.1\r\n"
10205 "Host: www.example.org\r\n"
10206 "Connection: keep-alive\r\n"
10207 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10208 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10209 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10210 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210211 };
10212
10213 // Sever accepts the authorization.
10214 MockRead data_reads1[] = {
10215 MockRead("HTTP/1.0 200 OK\r\n"),
10216 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610217 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210218 };
10219
Ryan Sleevib8d7ea02018-05-07 20:01:0110220 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710221 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210222
[email protected]49639fa2011-12-20 23:22:4110223 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210224
tfarina42834112016-09-22 13:38:2010225 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210227
10228 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110229 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210230
bnc691fda62016-08-12 00:43:1610231 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210232 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810233 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210234 }
10235}
10236
[email protected]89ceba9a2009-03-21 03:46:0610237// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110238TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610239 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910240 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610241 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610242
10243 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410244 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610245 trans.read_buf_len_ = 15;
10246 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610247
10248 // Setup state in response_
bnc691fda62016-08-12 00:43:1610249 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810250 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810251 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710252 response->response_time = base::Time::Now();
10253 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610254
10255 { // Setup state for response_.vary_data
10256 HttpRequestInfo request;
10257 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10258 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710259 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310260 request.extra_headers.SetHeader("Foo", "1");
10261 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010262 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610263 }
10264
10265 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610266 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610267
10268 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610269 EXPECT_FALSE(trans.read_buf_);
10270 EXPECT_EQ(0, trans.read_buf_len_);
10271 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810272 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210273 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410274 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810275 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710276 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610277}
10278
[email protected]bacff652009-03-31 17:50:3310279// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110280TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310281 HttpRequestInfo request;
10282 request.method = "GET";
bncce36dca22015-04-21 22:11:2310283 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010284 request.traffic_annotation =
10285 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310286
danakj1fd259a02016-04-16 03:17:0910287 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610288 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710289
[email protected]bacff652009-03-31 17:50:3310290 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310291 MockWrite(
10292 "GET / HTTP/1.1\r\n"
10293 "Host: www.example.org\r\n"
10294 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310295 };
10296
10297 MockRead data_reads[] = {
10298 MockRead("HTTP/1.0 200 OK\r\n"),
10299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10300 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610301 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310302 };
10303
[email protected]5ecc992a42009-11-11 01:41:5910304 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110305 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610306 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10307 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310308
[email protected]bb88e1d32013-05-03 23:11:0710309 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10310 session_deps_.socket_factory->AddSocketDataProvider(&data);
10311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10312 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310313
[email protected]49639fa2011-12-20 23:22:4110314 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310315
tfarina42834112016-09-22 13:38:2010316 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310318
10319 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110320 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310321
bnc691fda62016-08-12 00:43:1610322 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110323 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310324
10325 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110326 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310327
bnc691fda62016-08-12 00:43:1610328 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310329
wezca1070932016-05-26 20:30:5210330 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310331 EXPECT_EQ(100, response->headers->GetContentLength());
10332}
10333
10334// Test HTTPS connections to a site with a bad certificate, going through a
10335// proxy
bncd16676a2016-07-20 16:23:0110336TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610337 session_deps_.proxy_resolution_service =
10338 ConfiguredProxyResolutionService::CreateFixed(
10339 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310340
10341 HttpRequestInfo request;
10342 request.method = "GET";
bncce36dca22015-04-21 22:11:2310343 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010344 request.traffic_annotation =
10345 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310346
10347 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710348 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10349 "Host: www.example.org:443\r\n"
10350 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310351 };
10352
10353 MockRead proxy_reads[] = {
10354 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610355 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310356 };
10357
10358 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710359 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10360 "Host: www.example.org:443\r\n"
10361 "Proxy-Connection: keep-alive\r\n\r\n"),
10362 MockWrite("GET / HTTP/1.1\r\n"
10363 "Host: www.example.org\r\n"
10364 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310365 };
10366
10367 MockRead data_reads[] = {
10368 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10369 MockRead("HTTP/1.0 200 OK\r\n"),
10370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10371 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610372 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310373 };
10374
Ryan Sleevib8d7ea02018-05-07 20:01:0110375 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10376 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610377 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10378 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310379
[email protected]bb88e1d32013-05-03 23:11:0710380 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10381 session_deps_.socket_factory->AddSocketDataProvider(&data);
10382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10383 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310384
[email protected]49639fa2011-12-20 23:22:4110385 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310386
10387 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710388 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310389
danakj1fd259a02016-04-16 03:17:0910390 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610391 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310392
tfarina42834112016-09-22 13:38:2010393 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110394 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310395
10396 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110397 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310398
bnc691fda62016-08-12 00:43:1610399 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110400 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310401
10402 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110403 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310404
bnc691fda62016-08-12 00:43:1610405 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310406
wezca1070932016-05-26 20:30:5210407 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310408 EXPECT_EQ(100, response->headers->GetContentLength());
10409 }
10410}
10411
[email protected]2df19bb2010-08-25 20:13:4610412
10413// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110414TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910415 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610416 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910417 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410418 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710419 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610420
10421 HttpRequestInfo request;
10422 request.method = "GET";
bncce36dca22015-04-21 22:11:2310423 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010424 request.traffic_annotation =
10425 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610426
10427 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710428 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10429 "Host: www.example.org:443\r\n"
10430 "Proxy-Connection: keep-alive\r\n\r\n"),
10431 MockWrite("GET / HTTP/1.1\r\n"
10432 "Host: www.example.org\r\n"
10433 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610434 };
10435
10436 MockRead data_reads[] = {
10437 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10438 MockRead("HTTP/1.1 200 OK\r\n"),
10439 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10440 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610441 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610442 };
10443
Ryan Sleevib8d7ea02018-05-07 20:01:0110444 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610445 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10446 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610447
[email protected]bb88e1d32013-05-03 23:11:0710448 session_deps_.socket_factory->AddSocketDataProvider(&data);
10449 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10450 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610451
[email protected]49639fa2011-12-20 23:22:4110452 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610453
danakj1fd259a02016-04-16 03:17:0910454 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610455 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610456
tfarina42834112016-09-22 13:38:2010457 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110458 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610459
10460 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110461 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610462 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610463
wezca1070932016-05-26 20:30:5210464 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610465
tbansal2ecbbc72016-10-06 17:15:4710466 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610467 EXPECT_TRUE(response->headers->IsKeepAlive());
10468 EXPECT_EQ(200, response->headers->response_code());
10469 EXPECT_EQ(100, response->headers->GetContentLength());
10470 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010471
10472 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610473 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010474 TestLoadTimingNotReusedWithPac(load_timing_info,
10475 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610476}
10477
Eric Roman695a7872019-04-16 21:53:2910478// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110479TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910480 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610481 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910482 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410483 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710484 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910485
Matt Menkeecfecfc72019-02-05 19:15:2810486 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10487 session_deps_.host_resolver->set_ondemand_mode(true);
10488
[email protected]511f6f52010-12-17 03:58:2910489 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210490 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910491 request.method = "GET";
bncce36dca22015-04-21 22:11:2310492 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010493 request.traffic_annotation =
10494 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910495
10496 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810497 MockWrite(ASYNC, 0,
10498 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710499 "Host: www.example.org:443\r\n"
10500 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910501 };
10502
10503 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810504 // Pause on first read.
10505 MockRead(ASYNC, ERR_IO_PENDING, 1),
10506 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10507 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10508 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910509 };
10510
Matt Menkeecfecfc72019-02-05 19:15:2810511 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610512 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910513
[email protected]bb88e1d32013-05-03 23:11:0710514 session_deps_.socket_factory->AddSocketDataProvider(&data);
10515 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910516
[email protected]49639fa2011-12-20 23:22:4110517 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910518
danakj1fd259a02016-04-16 03:17:0910519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610520 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910521
tfarina42834112016-09-22 13:38:2010522 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810524 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10525
10526 // Host resolution takes |kTimeIncrement|.
10527 FastForwardBy(kTimeIncrement);
10528 // Resolving the current request with |ResolveNow| will cause the pending
10529 // request to instantly complete, and the async connect will start as well.
10530 session_deps_.host_resolver->ResolveOnlyRequestNow();
10531
10532 // Connecting takes |kTimeIncrement|.
10533 FastForwardBy(kTimeIncrement);
10534 data.RunUntilPaused();
10535
10536 // The server takes |kTimeIncrement| to respond.
10537 FastForwardBy(kTimeIncrement);
10538 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910539
10540 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910541 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910542}
10543
Eric Roman74103c72019-02-21 00:23:1210544// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10545TEST_F(HttpNetworkTransactionTest,
10546 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10547 base::HistogramTester histograms;
10548 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610549 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Eric Roman74103c72019-02-21 00:23:1210550 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410551 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210552 session_deps_.net_log = &net_log;
10553
10554 HttpRequestInfo request;
10555 request.method = "GET";
10556 request.url = GURL("https://www.example.org/");
10557 request.traffic_annotation =
10558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10559
10560 MockWrite data_writes[] = {
10561 MockWrite(ASYNC, 0,
10562 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10563 "Host: www.example.org:443\r\n"
10564 "Proxy-Connection: keep-alive\r\n\r\n"),
10565 };
10566
10567 MockRead data_reads[] = {
10568 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10569 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10570 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10571 };
10572
10573 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10574 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10575
10576 session_deps_.socket_factory->AddSocketDataProvider(&data);
10577 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10578
10579 TestCompletionCallback callback;
10580
10581 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10582 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10583
10584 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10585 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10586
10587 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910588 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210589}
10590
10591// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10592// request for main frames.
10593TEST_F(HttpNetworkTransactionTest,
10594 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10595 base::HistogramTester histograms;
10596 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610597 ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
Eric Roman74103c72019-02-21 00:23:1210598 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410599 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210600 session_deps_.net_log = &net_log;
10601
10602 HttpRequestInfo request;
10603 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10604 request.method = "GET";
10605 request.url = GURL("https://www.example.org/");
10606 request.traffic_annotation =
10607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10608
10609 MockWrite data_writes[] = {
10610 MockWrite(ASYNC, 0,
10611 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10612 "Host: www.example.org:443\r\n"
10613 "Proxy-Connection: keep-alive\r\n\r\n"),
10614 };
10615
10616 MockRead data_reads[] = {
10617 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10618 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10619 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10620 };
10621
10622 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10623 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10624
10625 session_deps_.socket_factory->AddSocketDataProvider(&data);
10626 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10627
10628 TestCompletionCallback callback;
10629
10630 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10631 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10632
10633 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10634 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10635
10636 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910637 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210638}
10639
Eric Roman695a7872019-04-16 21:53:2910640// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210641// frames.
bncd16676a2016-07-20 16:23:0110642TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210643 base::HistogramTester histograms;
Nicolas Arciniegad2013f92020-02-07 23:00:5610644 session_deps_.proxy_resolution_service =
10645 ConfiguredProxyResolutionService::CreateFixed(
10646 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410647 RecordingTestNetLog net_log;
Matt Menkeecfecfc72019-02-05 19:15:2810648 session_deps_.net_log = &net_log;
10649
Matt Menkeecfecfc72019-02-05 19:15:2810650 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10651 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910652
10653 HttpRequestInfo request;
10654 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210655 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310656 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010657 request.traffic_annotation =
10658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910659
Ryan Hamilton0239aac2018-05-19 00:03:1310660 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410661 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10662 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310663 spdy::SpdySerializedFrame goaway(
10664 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910665 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110666 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810667 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910668 };
10669
10670 static const char* const kExtraHeaders[] = {
10671 "location",
10672 "http://login.example.com/",
10673 };
Ryan Hamilton0239aac2018-05-19 00:03:1310674 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410675 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910676 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810677 // Pause on first read.
10678 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10679 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910680 };
10681
Matt Menkeecfecfc72019-02-05 19:15:2810682 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610683 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610684 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910685
[email protected]bb88e1d32013-05-03 23:11:0710686 session_deps_.socket_factory->AddSocketDataProvider(&data);
10687 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910688
[email protected]49639fa2011-12-20 23:22:4110689 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910690
danakj1fd259a02016-04-16 03:17:0910691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910693
tfarina42834112016-09-22 13:38:2010694 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110695 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810696 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2910697
Matt Menkeecfecfc72019-02-05 19:15:2810698 // Host resolution takes |kTimeIncrement|.
10699 FastForwardBy(kTimeIncrement);
10700 // Resolving the current request with |ResolveNow| will cause the pending
10701 // request to instantly complete, and the async connect will start as well.
10702 session_deps_.host_resolver->ResolveOnlyRequestNow();
10703
10704 // Connecting takes |kTimeIncrement|.
10705 FastForwardBy(kTimeIncrement);
10706 data.RunUntilPaused();
10707
10708 FastForwardBy(kTimeIncrement);
10709 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910710 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910711 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910712}
10713
[email protected]4eddbc732012-08-09 05:40:1710714// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110715TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610716 session_deps_.proxy_resolution_service =
10717 ConfiguredProxyResolutionService::CreateFixed(
10718 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910719
10720 HttpRequestInfo request;
10721 request.method = "GET";
bncce36dca22015-04-21 22:11:2310722 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010723 request.traffic_annotation =
10724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910725
10726 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710727 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10728 "Host: www.example.org:443\r\n"
10729 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910730 };
10731
10732 MockRead data_reads[] = {
10733 MockRead("HTTP/1.1 404 Not Found\r\n"),
10734 MockRead("Content-Length: 23\r\n\r\n"),
10735 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0610736 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2910737 };
10738
Ryan Sleevib8d7ea02018-05-07 20:01:0110739 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610740 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910741
[email protected]bb88e1d32013-05-03 23:11:0710742 session_deps_.socket_factory->AddSocketDataProvider(&data);
10743 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910744
[email protected]49639fa2011-12-20 23:22:4110745 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910746
danakj1fd259a02016-04-16 03:17:0910747 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610748 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910749
tfarina42834112016-09-22 13:38:2010750 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110751 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910752
10753 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110754 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910755
ttuttle960fcbf2016-04-19 13:26:3210756 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910757}
10758
[email protected]4eddbc732012-08-09 05:40:1710759// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110760TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610761 session_deps_.proxy_resolution_service =
10762 ConfiguredProxyResolutionService::CreateFixed(
10763 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910764
10765 HttpRequestInfo request;
10766 request.method = "GET";
bncce36dca22015-04-21 22:11:2310767 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010768 request.traffic_annotation =
10769 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910770
Ryan Hamilton0239aac2018-05-19 00:03:1310771 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410772 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10773 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310774 spdy::SpdySerializedFrame rst(
10775 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910776 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110777 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2910778 };
10779
10780 static const char* const kExtraHeaders[] = {
10781 "location",
10782 "http://login.example.com/",
10783 };
Ryan Hamilton0239aac2018-05-19 00:03:1310784 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410785 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1310786 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1910787 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2910788 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110789 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310790 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910791 };
10792
Ryan Sleevib8d7ea02018-05-07 20:01:0110793 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610794 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610795 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910796
[email protected]bb88e1d32013-05-03 23:11:0710797 session_deps_.socket_factory->AddSocketDataProvider(&data);
10798 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910799
[email protected]49639fa2011-12-20 23:22:4110800 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910801
danakj1fd259a02016-04-16 03:17:0910802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610803 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910804
tfarina42834112016-09-22 13:38:2010805 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910807
10808 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110809 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910810
ttuttle960fcbf2016-04-19 13:26:3210811 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910812}
10813
[email protected]0c5fb722012-02-28 11:50:3510814// Test the request-challenge-retry sequence for basic auth, through
10815// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110816TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510817 HttpRequestInfo request;
10818 request.method = "GET";
bncce36dca22015-04-21 22:11:2310819 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510820 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910821 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:1010822 request.traffic_annotation =
10823 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510824
10825 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910826 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610827 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910828 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410829 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710830 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910831 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510832
10833 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310834 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410835 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10836 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310837 spdy::SpdySerializedFrame rst(
10838 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810839 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510840
bnc691fda62016-08-12 00:43:1610841 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510842 // be issuing -- the final header line contains the credentials.
10843 const char* const kAuthCredentials[] = {
10844 "proxy-authorization", "Basic Zm9vOmJhcg==",
10845 };
Ryan Hamilton0239aac2018-05-19 00:03:1310846 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410847 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10848 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310849 HostPortPair("www.example.org", 443)));
10850 // fetch https://www.example.org/ via HTTP
10851 const char get[] =
10852 "GET / HTTP/1.1\r\n"
10853 "Host: www.example.org\r\n"
10854 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310855 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910856 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510857
10858 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110859 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10860 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510861 };
10862
10863 // The proxy responds to the connect with a 407, using a persistent
10864 // connection.
thestig9d3bb0c2015-01-24 00:49:5110865 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510866 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510867 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10868 };
Ryan Hamilton0239aac2018-05-19 00:03:1310869 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410870 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510871
Ryan Hamilton0239aac2018-05-19 00:03:1310872 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510873 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510874 const char resp[] = "HTTP/1.1 200 OK\r\n"
10875 "Content-Length: 5\r\n\r\n";
10876
Ryan Hamilton0239aac2018-05-19 00:03:1310877 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910878 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310879 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910880 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510881 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110882 CreateMockRead(conn_auth_resp, 1, ASYNC),
10883 CreateMockRead(conn_resp, 4, ASYNC),
10884 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10885 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310886 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510887 };
10888
Ryan Sleevib8d7ea02018-05-07 20:01:0110889 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710890 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510891 // Negotiate SPDY to the proxy
10892 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610893 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710894 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510895 // Vanilla SSL to the server
10896 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710897 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510898
10899 TestCompletionCallback callback1;
10900
bnc87dcefc2017-05-25 12:47:5810901 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910902 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510903
10904 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510906
10907 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110908 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410909 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510910 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010911 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10912 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510913 ExpectLogContainsSomewhere(
10914 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010915 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10916 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510917
10918 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210919 ASSERT_TRUE(response);
10920 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510921 EXPECT_EQ(407, response->headers->response_code());
10922 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810923 EXPECT_TRUE(response->auth_challenge.has_value());
10924 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510925
10926 TestCompletionCallback callback2;
10927
10928 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10929 callback2.callback());
robpercival214763f2016-07-01 23:27:0110930 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510931
10932 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110933 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510934
10935 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210936 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510937
10938 EXPECT_TRUE(response->headers->IsKeepAlive());
10939 EXPECT_EQ(200, response->headers->response_code());
10940 EXPECT_EQ(5, response->headers->GetContentLength());
10941 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10942
10943 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810944 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510945
[email protected]029c83b62013-01-24 05:28:2010946 LoadTimingInfo load_timing_info;
10947 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10948 TestLoadTimingNotReusedWithPac(load_timing_info,
10949 CONNECT_TIMING_HAS_SSL_TIMES);
10950
[email protected]0c5fb722012-02-28 11:50:3510951 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1110952 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]0c5fb722012-02-28 11:50:3510953}
10954
[email protected]7c6f7ba2012-04-03 04:09:2910955// Test that an explicitly trusted SPDY proxy can push a resource from an
10956// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110957TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510958 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910959 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510960 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10961 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910962 HttpRequestInfo request;
10963 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1010964 request.traffic_annotation =
10965 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910966
[email protected]7c6f7ba2012-04-03 04:09:2910967 request.method = "GET";
bncce36dca22015-04-21 22:11:2310968 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910969 push_request.method = "GET";
10970 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1010971 push_request.traffic_annotation =
10972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910973
tbansal28e68f82016-02-04 02:56:1510974 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910975 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610976 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910977 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410978 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710979 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010980
Eric Roman3d8546a2018-09-10 17:00:5210981 session_deps_.proxy_resolution_service->SetProxyDelegate(
10982 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010983
danakj1fd259a02016-04-16 03:17:0910984 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910985
Ryan Hamilton0239aac2018-05-19 00:03:1310986 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510987 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310988 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510989 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910990
10991 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110992 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510993 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910994 };
10995
Ryan Hamilton0239aac2018-05-19 00:03:1310996 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510997 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610998
Ryan Hamilton0239aac2018-05-19 00:03:1310999 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511000 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2911001
Ryan Hamilton0239aac2018-05-19 00:03:1311002 spdy::SpdySerializedFrame stream1_body(
11003 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2911004
Ryan Hamilton0239aac2018-05-19 00:03:1311005 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1911006 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2911007
11008 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3611009 CreateMockRead(stream2_syn, 1, ASYNC),
11010 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511011 CreateMockRead(stream1_body, 4, ASYNC),
11012 CreateMockRead(stream2_body, 5, ASYNC),
11013 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2911014 };
11015
Ryan Sleevib8d7ea02018-05-07 20:01:0111016 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711017 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2911018 // Negotiate SPDY to the proxy
11019 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611020 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711021 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2911022
bnc87dcefc2017-05-25 12:47:5811023 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911024 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2911025 TestCompletionCallback callback;
11026 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111027 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911028
11029 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111030 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911031 const HttpResponseInfo* response = trans->GetResponseInfo();
11032
bnc87dcefc2017-05-25 12:47:5811033 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1911034 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5011035 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111036 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911037
11038 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111039 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911040 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
11041
wezca1070932016-05-26 20:30:5211042 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2911043 EXPECT_TRUE(response->headers->IsKeepAlive());
11044
11045 EXPECT_EQ(200, response->headers->response_code());
11046 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11047
11048 std::string response_data;
11049 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111050 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911051 EXPECT_EQ("hello!", response_data);
11052
[email protected]029c83b62013-01-24 05:28:2011053 LoadTimingInfo load_timing_info;
11054 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11055 TestLoadTimingNotReusedWithPac(load_timing_info,
11056 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11057
[email protected]7c6f7ba2012-04-03 04:09:2911058 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5211059 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2911060 EXPECT_EQ(200, push_response->headers->response_code());
11061
11062 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111063 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911064 EXPECT_EQ("pushed", response_data);
11065
[email protected]029c83b62013-01-24 05:28:2011066 LoadTimingInfo push_load_timing_info;
11067 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
11068 TestLoadTimingReusedWithPac(push_load_timing_info);
11069 // The transactions should share a socket ID, despite being for different
11070 // origins.
11071 EXPECT_EQ(load_timing_info.socket_log_id,
11072 push_load_timing_info.socket_log_id);
11073
[email protected]7c6f7ba2012-04-03 04:09:2911074 trans.reset();
11075 push_trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111076 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]7c6f7ba2012-04-03 04:09:2911077}
11078
[email protected]8c843192012-04-05 07:15:0011079// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0111080TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511081 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911082 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511083 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11084 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0011085 HttpRequestInfo request;
11086
11087 request.method = "GET";
bncce36dca22015-04-21 22:11:2311088 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011089 request.traffic_annotation =
11090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0011091
Nicolas Arciniegad2013f92020-02-07 23:00:5611092 session_deps_.proxy_resolution_service =
11093 ConfiguredProxyResolutionService::CreateFixed(
11094 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411095 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711096 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011097
11098 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211099 session_deps_.proxy_resolution_service->SetProxyDelegate(
11100 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011101
danakj1fd259a02016-04-16 03:17:0911102 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0011103
Ryan Hamilton0239aac2018-05-19 00:03:1311104 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511105 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0011106
Ryan Hamilton0239aac2018-05-19 00:03:1311107 spdy::SpdySerializedFrame push_rst(
11108 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011109
11110 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111111 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011112 };
11113
Ryan Hamilton0239aac2018-05-19 00:03:1311114 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511115 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011116
Ryan Hamilton0239aac2018-05-19 00:03:1311117 spdy::SpdySerializedFrame stream1_body(
11118 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011119
Ryan Hamilton0239aac2018-05-19 00:03:1311120 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511121 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011122
11123 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111124 CreateMockRead(stream1_reply, 1, ASYNC),
11125 CreateMockRead(stream2_syn, 2, ASYNC),
11126 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911127 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011128 };
11129
Ryan Sleevib8d7ea02018-05-07 20:01:0111130 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711131 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011132 // Negotiate SPDY to the proxy
11133 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611134 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711135 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011136
bnc87dcefc2017-05-25 12:47:5811137 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911138 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011139 TestCompletionCallback callback;
11140 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011142
11143 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111144 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011145 const HttpResponseInfo* response = trans->GetResponseInfo();
11146
wezca1070932016-05-26 20:30:5211147 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011148 EXPECT_TRUE(response->headers->IsKeepAlive());
11149
11150 EXPECT_EQ(200, response->headers->response_code());
11151 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11152
11153 std::string response_data;
11154 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111155 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011156 EXPECT_EQ("hello!", response_data);
11157
11158 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111159 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]8c843192012-04-05 07:15:0011160}
11161
tbansal8ef1d3e2016-02-03 04:05:4211162// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11163// resources.
bncd16676a2016-07-20 16:23:0111164TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511165 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911166 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511167 proxy_delegate->set_trusted_spdy_proxy(
11168 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11169
tbansal8ef1d3e2016-02-03 04:05:4211170 HttpRequestInfo request;
11171
11172 request.method = "GET";
11173 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011174 request.traffic_annotation =
11175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211176
11177 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:5611178 session_deps_.proxy_resolution_service =
11179 ConfiguredProxyResolutionService::CreateFixed(
11180 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411181 RecordingBoundTestNetLog log;
tbansal8ef1d3e2016-02-03 04:05:4211182 session_deps_.net_log = log.bound().net_log();
11183
11184 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211185 session_deps_.proxy_resolution_service->SetProxyDelegate(
11186 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211187
danakj1fd259a02016-04-16 03:17:0911188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211189
Ryan Hamilton0239aac2018-05-19 00:03:1311190 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511191 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311192 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511193 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211194
11195 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111196 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511197 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211198 };
11199
Ryan Hamilton0239aac2018-05-19 00:03:1311200 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511201 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211202
Ryan Hamilton0239aac2018-05-19 00:03:1311203 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311204 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911205
Ryan Hamilton0239aac2018-05-19 00:03:1311206 spdy::SpdySerializedFrame stream1_body(
11207 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211208
Ryan Hamilton0239aac2018-05-19 00:03:1311209 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511210 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211211
Ryan Hamilton0239aac2018-05-19 00:03:1311212 spdy::SpdySerializedFrame stream2_body(
11213 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211214
11215 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111216 CreateMockRead(stream1_reply, 1, ASYNC),
11217 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511218 CreateMockRead(stream1_body, 4, ASYNC),
11219 CreateMockRead(stream2_body, 5, ASYNC),
11220 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211221 };
11222
Ryan Sleevib8d7ea02018-05-07 20:01:0111223 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211224 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11225 // Negotiate SPDY to the proxy
11226 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611227 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211228 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11229
bnc87dcefc2017-05-25 12:47:5811230 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911231 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211232 TestCompletionCallback callback;
11233 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111234 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211235
11236 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111237 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211238 const HttpResponseInfo* response = trans->GetResponseInfo();
11239
wezca1070932016-05-26 20:30:5211240 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211241 EXPECT_TRUE(response->headers->IsKeepAlive());
11242
11243 EXPECT_EQ(200, response->headers->response_code());
11244 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11245
11246 std::string response_data;
11247 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111248 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211249 EXPECT_EQ("hello!", response_data);
11250
11251 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111252 session->CloseAllConnections(ERR_FAILED, "Very good reason");
tbansal8ef1d3e2016-02-03 04:05:4211253}
11254
[email protected]2df19bb2010-08-25 20:13:4611255// Test HTTPS connections to a site with a bad certificate, going through an
11256// HTTPS proxy
bncd16676a2016-07-20 16:23:0111257TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611258 session_deps_.proxy_resolution_service =
11259 ConfiguredProxyResolutionService::CreateFixed(
11260 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611261
11262 HttpRequestInfo request;
11263 request.method = "GET";
bncce36dca22015-04-21 22:11:2311264 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011265 request.traffic_annotation =
11266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611267
11268 // Attempt to fetch the URL from a server with a bad cert
11269 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711270 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11271 "Host: www.example.org:443\r\n"
11272 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611273 };
11274
11275 MockRead bad_cert_reads[] = {
11276 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611277 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611278 };
11279
11280 // Attempt to fetch the URL with a good cert
11281 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711282 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11283 "Host: www.example.org:443\r\n"
11284 "Proxy-Connection: keep-alive\r\n\r\n"),
11285 MockWrite("GET / HTTP/1.1\r\n"
11286 "Host: www.example.org\r\n"
11287 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611288 };
11289
11290 MockRead good_cert_reads[] = {
11291 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11292 MockRead("HTTP/1.0 200 OK\r\n"),
11293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11294 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611295 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611296 };
11297
Ryan Sleevib8d7ea02018-05-07 20:01:0111298 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11299 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611300 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11301 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611302
11303 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711304 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11305 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11306 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611307
11308 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11310 session_deps_.socket_factory->AddSocketDataProvider(&data);
11311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611312
[email protected]49639fa2011-12-20 23:22:4111313 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611314
danakj1fd259a02016-04-16 03:17:0911315 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611316 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611317
tfarina42834112016-09-22 13:38:2011318 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111319 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611320
11321 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111322 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611323
bnc691fda62016-08-12 00:43:1611324 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611326
11327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111328 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611329
bnc691fda62016-08-12 00:43:1611330 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611331
wezca1070932016-05-26 20:30:5211332 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611333 EXPECT_EQ(100, response->headers->GetContentLength());
11334}
11335
bncd16676a2016-07-20 16:23:0111336TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211337 HttpRequestInfo request;
11338 request.method = "GET";
bncce36dca22015-04-21 22:11:2311339 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311340 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11341 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1011342 request.traffic_annotation =
11343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211344
danakj1fd259a02016-04-16 03:17:0911345 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611346 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711347
[email protected]1c773ea12009-04-28 19:58:4211348 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311349 MockWrite(
11350 "GET / HTTP/1.1\r\n"
11351 "Host: www.example.org\r\n"
11352 "Connection: keep-alive\r\n"
11353 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211354 };
11355
11356 // Lastly, the server responds with the actual content.
11357 MockRead data_reads[] = {
11358 MockRead("HTTP/1.0 200 OK\r\n"),
11359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11360 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611361 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211362 };
11363
Ryan Sleevib8d7ea02018-05-07 20:01:0111364 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711365 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211366
[email protected]49639fa2011-12-20 23:22:4111367 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211368
tfarina42834112016-09-22 13:38:2011369 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211371
11372 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111373 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211374}
11375
bncd16676a2016-07-20 16:23:0111376TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011377 // Test user agent values, used both for the request header of the original
11378 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11379 // no request header / no HttpUserAgentSettings object.
11380 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911381
Matt Menked732ea42019-03-08 12:05:0011382 for (const char* setting_user_agent : kTestUserAgents) {
11383 if (!setting_user_agent) {
11384 session_deps_.http_user_agent_settings.reset();
11385 } else {
11386 session_deps_.http_user_agent_settings =
11387 std::make_unique<StaticHttpUserAgentSettings>(
11388 std::string() /* accept-language */, setting_user_agent);
11389 }
11390 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611391 ConfiguredProxyResolutionService::CreateFixed(
11392 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked732ea42019-03-08 12:05:0011393 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11394 for (const char* request_user_agent : kTestUserAgents) {
11395 HttpRequestInfo request;
11396 request.method = "GET";
11397 request.url = GURL("https://www.example.org/");
11398 if (request_user_agent) {
11399 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11400 request_user_agent);
11401 }
11402 request.traffic_annotation =
11403 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711404
Matt Menked732ea42019-03-08 12:05:0011405 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911406
Matt Menked732ea42019-03-08 12:05:0011407 std::string expected_request;
11408 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11409 expected_request =
11410 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11411 "Host: www.example.org:443\r\n"
11412 "Proxy-Connection: keep-alive\r\n\r\n";
11413 } else {
11414 expected_request = base::StringPrintf(
11415 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11416 "Host: www.example.org:443\r\n"
11417 "Proxy-Connection: keep-alive\r\n"
11418 "User-Agent: %s\r\n\r\n",
11419 setting_user_agent);
11420 }
11421 MockWrite data_writes[] = {
11422 MockWrite(expected_request.c_str()),
11423 };
11424 MockRead data_reads[] = {
11425 // Return an error, so the transaction stops here (this test isn't
11426 // interested in the rest).
11427 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11428 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11429 MockRead("Proxy-Connection: close\r\n\r\n"),
11430 };
[email protected]da81f132010-08-18 23:39:2911431
Matt Menked732ea42019-03-08 12:05:0011432 StaticSocketDataProvider data(data_reads, data_writes);
11433 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911434
Matt Menked732ea42019-03-08 12:05:0011435 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911436
Matt Menked732ea42019-03-08 12:05:0011437 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11438 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11439
11440 rv = callback.WaitForResult();
11441 EXPECT_THAT(rv, IsOk());
11442 }
11443 }
[email protected]da81f132010-08-18 23:39:2911444}
11445
bncd16676a2016-07-20 16:23:0111446TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211447 HttpRequestInfo request;
11448 request.method = "GET";
bncce36dca22015-04-21 22:11:2311449 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611450 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11451 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011452 request.traffic_annotation =
11453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211454
danakj1fd259a02016-04-16 03:17:0911455 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611456 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711457
[email protected]1c773ea12009-04-28 19:58:4211458 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311459 MockWrite(
11460 "GET / HTTP/1.1\r\n"
11461 "Host: www.example.org\r\n"
11462 "Connection: keep-alive\r\n"
11463 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211464 };
11465
11466 // Lastly, the server responds with the actual content.
11467 MockRead data_reads[] = {
11468 MockRead("HTTP/1.0 200 OK\r\n"),
11469 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11470 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611471 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211472 };
11473
Ryan Sleevib8d7ea02018-05-07 20:01:0111474 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711475 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211476
[email protected]49639fa2011-12-20 23:22:4111477 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211478
tfarina42834112016-09-22 13:38:2011479 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111480 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211481
11482 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111483 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211484}
11485
bncd16676a2016-07-20 16:23:0111486TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211487 HttpRequestInfo request;
11488 request.method = "POST";
bncce36dca22015-04-21 22:11:2311489 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011490 request.traffic_annotation =
11491 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211492
danakj1fd259a02016-04-16 03:17:0911493 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611494 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711495
[email protected]1c773ea12009-04-28 19:58:4211496 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311497 MockWrite(
11498 "POST / HTTP/1.1\r\n"
11499 "Host: www.example.org\r\n"
11500 "Connection: keep-alive\r\n"
11501 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211502 };
11503
11504 // Lastly, the server responds with the actual content.
11505 MockRead data_reads[] = {
11506 MockRead("HTTP/1.0 200 OK\r\n"),
11507 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11508 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611509 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211510 };
11511
Ryan Sleevib8d7ea02018-05-07 20:01:0111512 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711513 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211514
[email protected]49639fa2011-12-20 23:22:4111515 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211516
tfarina42834112016-09-22 13:38:2011517 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211519
11520 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111521 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211522}
11523
bncd16676a2016-07-20 16:23:0111524TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211525 HttpRequestInfo request;
11526 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311527 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011528 request.traffic_annotation =
11529 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211530
danakj1fd259a02016-04-16 03:17:0911531 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611532 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711533
[email protected]1c773ea12009-04-28 19:58:4211534 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311535 MockWrite(
11536 "PUT / HTTP/1.1\r\n"
11537 "Host: www.example.org\r\n"
11538 "Connection: keep-alive\r\n"
11539 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211540 };
11541
11542 // Lastly, the server responds with the actual content.
11543 MockRead data_reads[] = {
11544 MockRead("HTTP/1.0 200 OK\r\n"),
11545 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11546 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611547 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211548 };
11549
Ryan Sleevib8d7ea02018-05-07 20:01:0111550 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711551 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211552
[email protected]49639fa2011-12-20 23:22:4111553 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211554
tfarina42834112016-09-22 13:38:2011555 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111556 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211557
11558 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111559 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211560}
11561
bncd16676a2016-07-20 16:23:0111562TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211563 HttpRequestInfo request;
11564 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311565 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011566 request.traffic_annotation =
11567 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211568
danakj1fd259a02016-04-16 03:17:0911569 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611570 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711571
[email protected]1c773ea12009-04-28 19:58:4211572 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311573 MockWrite("HEAD / HTTP/1.1\r\n"
11574 "Host: www.example.org\r\n"
11575 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211576 };
11577
11578 // Lastly, the server responds with the actual content.
11579 MockRead data_reads[] = {
11580 MockRead("HTTP/1.0 200 OK\r\n"),
11581 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11582 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611583 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211584 };
11585
Ryan Sleevib8d7ea02018-05-07 20:01:0111586 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711587 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211588
[email protected]49639fa2011-12-20 23:22:4111589 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211590
tfarina42834112016-09-22 13:38:2011591 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111592 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211593
11594 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111595 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211596}
11597
bncd16676a2016-07-20 16:23:0111598TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211599 HttpRequestInfo request;
11600 request.method = "GET";
bncce36dca22015-04-21 22:11:2311601 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211602 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011603 request.traffic_annotation =
11604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211605
danakj1fd259a02016-04-16 03:17:0911606 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611607 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711608
[email protected]1c773ea12009-04-28 19:58:4211609 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311610 MockWrite(
11611 "GET / HTTP/1.1\r\n"
11612 "Host: www.example.org\r\n"
11613 "Connection: keep-alive\r\n"
11614 "Pragma: no-cache\r\n"
11615 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211616 };
11617
11618 // Lastly, the server responds with the actual content.
11619 MockRead data_reads[] = {
11620 MockRead("HTTP/1.0 200 OK\r\n"),
11621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11622 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611623 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211624 };
11625
Ryan Sleevib8d7ea02018-05-07 20:01:0111626 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711627 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211628
[email protected]49639fa2011-12-20 23:22:4111629 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211630
tfarina42834112016-09-22 13:38:2011631 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211633
11634 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111635 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211636}
11637
bncd16676a2016-07-20 16:23:0111638TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211639 HttpRequestInfo request;
11640 request.method = "GET";
bncce36dca22015-04-21 22:11:2311641 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211642 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1011643 request.traffic_annotation =
11644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211645
danakj1fd259a02016-04-16 03:17:0911646 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611647 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711648
[email protected]1c773ea12009-04-28 19:58:4211649 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311650 MockWrite(
11651 "GET / HTTP/1.1\r\n"
11652 "Host: www.example.org\r\n"
11653 "Connection: keep-alive\r\n"
11654 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211655 };
11656
11657 // Lastly, the server responds with the actual content.
11658 MockRead data_reads[] = {
11659 MockRead("HTTP/1.0 200 OK\r\n"),
11660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11661 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611662 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211663 };
11664
Ryan Sleevib8d7ea02018-05-07 20:01:0111665 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711666 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211667
[email protected]49639fa2011-12-20 23:22:4111668 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211669
tfarina42834112016-09-22 13:38:2011670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211672
11673 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111674 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211675}
11676
bncd16676a2016-07-20 16:23:0111677TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211678 HttpRequestInfo request;
11679 request.method = "GET";
bncce36dca22015-04-21 22:11:2311680 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311681 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1011682 request.traffic_annotation =
11683 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211684
danakj1fd259a02016-04-16 03:17:0911685 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611686 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711687
[email protected]1c773ea12009-04-28 19:58:4211688 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311689 MockWrite(
11690 "GET / HTTP/1.1\r\n"
11691 "Host: www.example.org\r\n"
11692 "Connection: keep-alive\r\n"
11693 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211694 };
11695
11696 // Lastly, the server responds with the actual content.
11697 MockRead data_reads[] = {
11698 MockRead("HTTP/1.0 200 OK\r\n"),
11699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11700 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611701 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211702 };
11703
Ryan Sleevib8d7ea02018-05-07 20:01:0111704 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711705 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211706
[email protected]49639fa2011-12-20 23:22:4111707 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211708
tfarina42834112016-09-22 13:38:2011709 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111710 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211711
11712 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111713 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211714}
11715
bncd16676a2016-07-20 16:23:0111716TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4711717 HttpRequestInfo request;
11718 request.method = "GET";
bncce36dca22015-04-21 22:11:2311719 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311720 request.extra_headers.SetHeader("referer", "www.foo.com");
11721 request.extra_headers.SetHeader("hEllo", "Kitty");
11722 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1011723 request.traffic_annotation =
11724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4711725
danakj1fd259a02016-04-16 03:17:0911726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611727 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711728
[email protected]270c6412010-03-29 22:02:4711729 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311730 MockWrite(
11731 "GET / HTTP/1.1\r\n"
11732 "Host: www.example.org\r\n"
11733 "Connection: keep-alive\r\n"
11734 "referer: www.foo.com\r\n"
11735 "hEllo: Kitty\r\n"
11736 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4711737 };
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]270c6412010-03-29 22:02:4711745 };
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]270c6412010-03-29 22:02:4711749
[email protected]49639fa2011-12-20 23:22:4111750 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4711751
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]270c6412010-03-29 22:02:4711754
11755 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111756 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4711757}
11758
bncd16676a2016-07-20 16:23:0111759TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711760 HttpRequestInfo request;
11761 request.method = "GET";
bncce36dca22015-04-21 22:11:2311762 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011763 request.traffic_annotation =
11764 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711765
Lily Houghton8c2f97d2018-01-22 05:06:5911766 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611767 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911768 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411769 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711770 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211771
danakj1fd259a02016-04-16 03:17:0911772 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611773 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211774
[email protected]3cd17242009-06-23 02:59:0211775 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11776 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11777
11778 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411779 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11780 MockWrite("GET / HTTP/1.1\r\n"
11781 "Host: www.example.org\r\n"
11782 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211783
11784 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411785 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11786 MockRead("HTTP/1.0 200 OK\r\n"),
11787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11788 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211789
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]3cd17242009-06-23 02:59:0211792
[email protected]49639fa2011-12-20 23:22:4111793 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211794
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]3cd17242009-06-23 02:59:0211797
11798 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111799 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211800
bnc691fda62016-08-12 00:43:1611801 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211802 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211803
tbansal2ecbbc72016-10-06 17:15:4711804 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011805 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611806 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011807 TestLoadTimingNotReusedWithPac(load_timing_info,
11808 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11809
[email protected]3cd17242009-06-23 02:59:0211810 std::string response_text;
bnc691fda62016-08-12 00:43:1611811 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111812 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211813 EXPECT_EQ("Payload", response_text);
11814}
11815
bncd16676a2016-07-20 16:23:0111816TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711817 HttpRequestInfo request;
11818 request.method = "GET";
bncce36dca22015-04-21 22:11:2311819 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011820 request.traffic_annotation =
11821 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711822
Lily Houghton8c2f97d2018-01-22 05:06:5911823 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611824 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911825 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411826 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711827 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211828
danakj1fd259a02016-04-16 03:17:0911829 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611830 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211831
[email protected]3cd17242009-06-23 02:59:0211832 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11833 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11834
11835 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311836 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411837 base::size(write_buffer)),
11838 MockWrite("GET / HTTP/1.1\r\n"
11839 "Host: www.example.org\r\n"
11840 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211841
11842 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411843 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11844 base::size(read_buffer)),
11845 MockRead("HTTP/1.0 200 OK\r\n"),
11846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11847 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511848
Ryan Sleevib8d7ea02018-05-07 20:01:0111849 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711850 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511851
[email protected]8ddf8322012-02-23 18:08:0611852 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511854
[email protected]49639fa2011-12-20 23:22:4111855 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511856
tfarina42834112016-09-22 13:38:2011857 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511859
11860 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111861 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511862
[email protected]029c83b62013-01-24 05:28:2011863 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611864 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011865 TestLoadTimingNotReusedWithPac(load_timing_info,
11866 CONNECT_TIMING_HAS_SSL_TIMES);
11867
bnc691fda62016-08-12 00:43:1611868 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211869 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711870 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511871
11872 std::string response_text;
bnc691fda62016-08-12 00:43:1611873 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111874 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511875 EXPECT_EQ("Payload", response_text);
11876}
11877
bncd16676a2016-07-20 16:23:0111878TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011879 HttpRequestInfo request;
11880 request.method = "GET";
bncce36dca22015-04-21 22:11:2311881 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011882 request.traffic_annotation =
11883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011884
Nicolas Arciniegad2013f92020-02-07 23:00:5611885 session_deps_.proxy_resolution_service =
11886 ConfiguredProxyResolutionService::CreateFixed(
11887 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411888 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711889 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011890
danakj1fd259a02016-04-16 03:17:0911891 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611892 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011893
11894 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11895 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11896
11897 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411898 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11899 MockWrite("GET / HTTP/1.1\r\n"
11900 "Host: www.example.org\r\n"
11901 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011902
11903 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411904 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11905 MockRead("HTTP/1.0 200 OK\r\n"),
11906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11907 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011908
Ryan Sleevib8d7ea02018-05-07 20:01:0111909 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711910 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011911
11912 TestCompletionCallback callback;
11913
tfarina42834112016-09-22 13:38:2011914 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111915 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011916
11917 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111918 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011919
bnc691fda62016-08-12 00:43:1611920 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211921 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011922
11923 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611924 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011925 TestLoadTimingNotReused(load_timing_info,
11926 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11927
11928 std::string response_text;
bnc691fda62016-08-12 00:43:1611929 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111930 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011931 EXPECT_EQ("Payload", response_text);
11932}
11933
bncd16676a2016-07-20 16:23:0111934TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711935 HttpRequestInfo request;
11936 request.method = "GET";
bncce36dca22015-04-21 22:11:2311937 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011938 request.traffic_annotation =
11939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711940
Lily Houghton8c2f97d2018-01-22 05:06:5911941 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611942 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911943 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411944 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711945 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511946
danakj1fd259a02016-04-16 03:17:0911947 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611948 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511949
[email protected]e0c27be2009-07-15 13:09:3511950 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11951 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711952 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311953 0x05, // Version
11954 0x01, // Command (CONNECT)
11955 0x00, // Reserved.
11956 0x03, // Address type (DOMAINNAME).
11957 0x0F, // Length of domain (15)
11958 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11959 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711960 };
[email protected]e0c27be2009-07-15 13:09:3511961 const char kSOCKS5OkResponse[] =
11962 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11963
11964 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411965 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11966 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11967 MockWrite("GET / HTTP/1.1\r\n"
11968 "Host: www.example.org\r\n"
11969 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511970
11971 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411972 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11973 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11974 MockRead("HTTP/1.0 200 OK\r\n"),
11975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11976 MockRead("Payload"),
11977 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511978
Ryan Sleevib8d7ea02018-05-07 20:01:0111979 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711980 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511981
[email protected]49639fa2011-12-20 23:22:4111982 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511983
tfarina42834112016-09-22 13:38:2011984 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111985 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511986
11987 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111988 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511989
bnc691fda62016-08-12 00:43:1611990 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211991 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711992 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511993
[email protected]029c83b62013-01-24 05:28:2011994 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611995 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011996 TestLoadTimingNotReusedWithPac(load_timing_info,
11997 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11998
[email protected]e0c27be2009-07-15 13:09:3511999 std::string response_text;
bnc691fda62016-08-12 00:43:1612000 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112001 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512002 EXPECT_EQ("Payload", response_text);
12003}
12004
bncd16676a2016-07-20 16:23:0112005TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712006 HttpRequestInfo request;
12007 request.method = "GET";
bncce36dca22015-04-21 22:11:2312008 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012009 request.traffic_annotation =
12010 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712011
Lily Houghton8c2f97d2018-01-22 05:06:5912012 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612013 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912014 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412015 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712016 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512017
danakj1fd259a02016-04-16 03:17:0912018 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612019 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512020
[email protected]e0c27be2009-07-15 13:09:3512021 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12022 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712023 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312024 0x05, // Version
12025 0x01, // Command (CONNECT)
12026 0x00, // Reserved.
12027 0x03, // Address type (DOMAINNAME).
12028 0x0F, // Length of domain (15)
12029 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12030 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3712031 };
12032
[email protected]e0c27be2009-07-15 13:09:3512033 const char kSOCKS5OkResponse[] =
12034 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
12035
12036 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412037 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2312038 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2412039 base::size(kSOCKS5OkRequest)),
12040 MockWrite("GET / HTTP/1.1\r\n"
12041 "Host: www.example.org\r\n"
12042 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512043
12044 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412045 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12046 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12047 MockRead("HTTP/1.0 200 OK\r\n"),
12048 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12049 MockRead("Payload"),
12050 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212051
Ryan Sleevib8d7ea02018-05-07 20:01:0112052 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712053 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212054
[email protected]8ddf8322012-02-23 18:08:0612055 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712056 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0212057
[email protected]49639fa2011-12-20 23:22:4112058 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212059
tfarina42834112016-09-22 13:38:2012060 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112061 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212062
12063 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112064 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212065
bnc691fda62016-08-12 00:43:1612066 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212067 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712068 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0212069
[email protected]029c83b62013-01-24 05:28:2012070 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612071 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012072 TestLoadTimingNotReusedWithPac(load_timing_info,
12073 CONNECT_TIMING_HAS_SSL_TIMES);
12074
[email protected]3cd17242009-06-23 02:59:0212075 std::string response_text;
bnc691fda62016-08-12 00:43:1612076 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112077 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212078 EXPECT_EQ("Payload", response_text);
12079}
12080
[email protected]448d4ca52012-03-04 04:12:2312081namespace {
12082
Matt Menkef6edce752019-03-19 17:21:5612083// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0612084
Matt Menkef6edce752019-03-19 17:21:5612085struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0612086 std::string proxy_server;
12087 std::string url;
Matt Menkef6edce752019-03-19 17:21:5612088 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1812089 bool ssl;
[email protected]2d731a32010-04-29 01:04:0612090};
12091
Matt Menkef6edce752019-03-19 17:21:5612092std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0712093 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0912094 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0612095
bnc525e175a2016-06-20 12:36:4012096 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312097 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112098 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1212099 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112100 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4212101 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0712102 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0612103
12104 return session;
12105}
12106
Matt Menkef6edce752019-03-19 17:21:5612107int GroupIdTransactionHelper(const std::string& url,
12108 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0612109 HttpRequestInfo request;
12110 request.method = "GET";
12111 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1012112 request.traffic_annotation =
12113 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612114
bnc691fda62016-08-12 00:43:1612115 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712116
[email protected]49639fa2011-12-20 23:22:4112117 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612118
12119 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012120 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612121}
12122
[email protected]448d4ca52012-03-04 04:12:2312123} // namespace
12124
Matt Menkef6edce752019-03-19 17:21:5612125TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12126 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312127 {
Matt Menkef6edce752019-03-19 17:21:5612128 "", // unused
12129 "http://www.example.org/direct",
12130 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12131 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412132 PrivacyMode::PRIVACY_MODE_DISABLED,
12133 NetworkIsolationKey(),
12134 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612135 false,
bncce36dca22015-04-21 22:11:2312136 },
12137 {
Matt Menkef6edce752019-03-19 17:21:5612138 "", // unused
12139 "http://[2001:1418:13:1::25]/direct",
12140 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12141 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412142 PrivacyMode::PRIVACY_MODE_DISABLED,
12143 NetworkIsolationKey(),
12144 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612145 false,
bncce36dca22015-04-21 22:11:2312146 },
[email protected]04e5be32009-06-26 20:00:3112147
bncce36dca22015-04-21 22:11:2312148 // SSL Tests
12149 {
Matt Menkef6edce752019-03-19 17:21:5612150 "", // unused
12151 "https://www.example.org/direct_ssl",
12152 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12153 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412154 PrivacyMode::PRIVACY_MODE_DISABLED,
12155 NetworkIsolationKey(),
12156 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612157 true,
bncce36dca22015-04-21 22:11:2312158 },
12159 {
Matt Menkef6edce752019-03-19 17:21:5612160 "", // unused
12161 "https://[2001:1418:13:1::25]/direct",
12162 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12163 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412164 PrivacyMode::PRIVACY_MODE_DISABLED,
12165 NetworkIsolationKey(),
12166 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612167 true,
bncce36dca22015-04-21 22:11:2312168 },
12169 {
Matt Menkef6edce752019-03-19 17:21:5612170 "", // unused
12171 "https://host.with.alternate/direct",
12172 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12173 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412174 PrivacyMode::PRIVACY_MODE_DISABLED,
12175 NetworkIsolationKey(),
12176 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612177 true,
bncce36dca22015-04-21 22:11:2312178 },
[email protected]2d731a32010-04-29 01:04:0612179 };
[email protected]2ff8b312010-04-26 22:20:5412180
Avi Drissman4365a4782018-12-28 19:26:2412181 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912182 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612183 ConfiguredProxyResolutionService::CreateFixed(
12184 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912185 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612186 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612187
mmenkee65e7af2015-10-13 17:16:4212188 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612189 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612190 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912191 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012192 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12193 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812194 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612195
12196 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612197 GroupIdTransactionHelper(tests[i].url, session.get()));
12198 EXPECT_EQ(tests[i].expected_group_id,
12199 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312200 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612201 }
[email protected]2d731a32010-04-29 01:04:0612202}
12203
Matt Menkef6edce752019-03-19 17:21:5612204TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12205 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312206 {
Matt Menke4802de62019-03-08 22:47:5012207 "http_proxy",
12208 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612209 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12210 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412211 PrivacyMode::PRIVACY_MODE_DISABLED,
12212 NetworkIsolationKey(),
12213 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012214 false,
bncce36dca22015-04-21 22:11:2312215 },
[email protected]2d731a32010-04-29 01:04:0612216
bncce36dca22015-04-21 22:11:2312217 // SSL Tests
12218 {
Matt Menke4802de62019-03-08 22:47:5012219 "http_proxy",
12220 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612221 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12222 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412223 PrivacyMode::PRIVACY_MODE_DISABLED,
12224 NetworkIsolationKey(),
12225 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012226 true,
bncce36dca22015-04-21 22:11:2312227 },
[email protected]af3490e2010-10-16 21:02:2912228
bncce36dca22015-04-21 22:11:2312229 {
Matt Menke4802de62019-03-08 22:47:5012230 "http_proxy",
12231 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612232 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12233 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412234 PrivacyMode::PRIVACY_MODE_DISABLED,
12235 NetworkIsolationKey(),
12236 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012237 true,
bncce36dca22015-04-21 22:11:2312238 },
[email protected]2d731a32010-04-29 01:04:0612239 };
12240
Avi Drissman4365a4782018-12-28 19:26:2412241 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912242 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612243 ConfiguredProxyResolutionService::CreateFixed(
12244 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912245 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612246 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612247
mmenkee65e7af2015-10-13 17:16:4212248 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612249
Matt Menkee8648fa2019-01-17 16:47:0712250 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12251 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612252 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612253 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912254 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012255 mock_pool_manager->SetSocketPool(proxy_server,
12256 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812257 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612258
12259 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612260 GroupIdTransactionHelper(tests[i].url, session.get()));
12261 EXPECT_EQ(tests[i].expected_group_id,
12262 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612263 }
[email protected]2d731a32010-04-29 01:04:0612264}
12265
Matt Menkef6edce752019-03-19 17:21:5612266TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12267 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312268 {
Matt Menke4802de62019-03-08 22:47:5012269 "socks4://socks_proxy:1080",
12270 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612271 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12272 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412273 PrivacyMode::PRIVACY_MODE_DISABLED,
12274 NetworkIsolationKey(),
12275 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012276 false,
bncce36dca22015-04-21 22:11:2312277 },
12278 {
Matt Menke4802de62019-03-08 22:47:5012279 "socks5://socks_proxy:1080",
12280 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612281 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12282 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412283 PrivacyMode::PRIVACY_MODE_DISABLED,
12284 NetworkIsolationKey(),
12285 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012286 false,
bncce36dca22015-04-21 22:11:2312287 },
[email protected]2d731a32010-04-29 01:04:0612288
bncce36dca22015-04-21 22:11:2312289 // SSL Tests
12290 {
Matt Menke4802de62019-03-08 22:47:5012291 "socks4://socks_proxy:1080",
12292 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612293 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12294 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412295 PrivacyMode::PRIVACY_MODE_DISABLED,
12296 NetworkIsolationKey(),
12297 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012298 true,
bncce36dca22015-04-21 22:11:2312299 },
12300 {
Matt Menke4802de62019-03-08 22:47:5012301 "socks5://socks_proxy:1080",
12302 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612303 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12304 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412305 PrivacyMode::PRIVACY_MODE_DISABLED,
12306 NetworkIsolationKey(),
12307 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012308 true,
bncce36dca22015-04-21 22:11:2312309 },
[email protected]af3490e2010-10-16 21:02:2912310
bncce36dca22015-04-21 22:11:2312311 {
Matt Menke4802de62019-03-08 22:47:5012312 "socks4://socks_proxy:1080",
12313 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612314 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12315 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412316 PrivacyMode::PRIVACY_MODE_DISABLED,
12317 NetworkIsolationKey(),
12318 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012319 true,
bncce36dca22015-04-21 22:11:2312320 },
[email protected]04e5be32009-06-26 20:00:3112321 };
12322
Avi Drissman4365a4782018-12-28 19:26:2412323 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912324 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612325 ConfiguredProxyResolutionService::CreateFixed(
12326 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912327 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612328 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212329
mmenkee65e7af2015-10-13 17:16:4212330 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112331
Matt Menkee8648fa2019-01-17 16:47:0712332 ProxyServer proxy_server(
12333 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12334 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612335 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612336 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912337 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012338 mock_pool_manager->SetSocketPool(proxy_server,
12339 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812340 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112341
bnc691fda62016-08-12 00:43:1612342 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112343
[email protected]2d731a32010-04-29 01:04:0612344 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612345 GroupIdTransactionHelper(tests[i].url, session.get()));
12346 EXPECT_EQ(tests[i].expected_group_id,
12347 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112348 }
12349}
12350
bncd16676a2016-07-20 16:23:0112351TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712352 HttpRequestInfo request;
12353 request.method = "GET";
bncce36dca22015-04-21 22:11:2312354 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012355 request.traffic_annotation =
12356 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712357
Nicolas Arciniegad2013f92020-02-07 23:00:5612358 session_deps_.proxy_resolution_service =
12359 ConfiguredProxyResolutionService::CreateFixed(
12360 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212361
[email protected]69719062010-01-05 20:09:2112362 // This simulates failure resolving all hostnames; that means we will fail
12363 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712364 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212365
danakj1fd259a02016-04-16 03:17:0912366 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612367 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512368
[email protected]49639fa2011-12-20 23:22:4112369 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512370
tfarina42834112016-09-22 13:38:2012371 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512373
[email protected]9172a982009-06-06 00:30:2512374 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112375 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512376}
12377
[email protected]0877e3d2009-10-17 22:29:5712378// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112379TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712380 HttpRequestInfo request;
12381 request.method = "GET";
12382 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012383 request.traffic_annotation =
12384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712385
12386 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612387 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712388 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112389 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712390 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912391 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712392
[email protected]49639fa2011-12-20 23:22:4112393 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712394
bnc691fda62016-08-12 00:43:1612395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712396
tfarina42834112016-09-22 13:38:2012397 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712399
12400 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112401 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912402
12403 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612404 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912405 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712406}
12407
zmo9528c9f42015-08-04 22:12:0812408// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112409TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712410 HttpRequestInfo request;
12411 request.method = "GET";
12412 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1012413 request.traffic_annotation =
12414 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712415
12416 MockRead data_reads[] = {
12417 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612418 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712419 };
12420
Ryan Sleevib8d7ea02018-05-07 20:01:0112421 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712422 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912423 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712424
[email protected]49639fa2011-12-20 23:22:4112425 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712426
bnc691fda62016-08-12 00:43:1612427 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712428
tfarina42834112016-09-22 13:38:2012429 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112430 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712431
12432 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112433 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812434
bnc691fda62016-08-12 00:43:1612435 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212436 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812437
wezca1070932016-05-26 20:30:5212438 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812439 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12440
12441 std::string response_data;
bnc691fda62016-08-12 00:43:1612442 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112443 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812444 EXPECT_EQ("", response_data);
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
12451// Make sure that a dropped connection while draining the body for auth
12452// restart does the right thing.
bncd16676a2016-07-20 16:23:0112453TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712454 HttpRequestInfo request;
12455 request.method = "GET";
bncce36dca22015-04-21 22:11:2312456 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012457 request.traffic_annotation =
12458 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712459
12460 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312461 MockWrite(
12462 "GET / HTTP/1.1\r\n"
12463 "Host: www.example.org\r\n"
12464 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712465 };
12466
12467 MockRead data_reads1[] = {
12468 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12469 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12470 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12471 MockRead("Content-Length: 14\r\n\r\n"),
12472 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612473 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712474 };
12475
Ryan Sleevib8d7ea02018-05-07 20:01:0112476 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712477 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712478
bnc691fda62016-08-12 00:43:1612479 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712480 // be issuing -- the final header line contains the credentials.
12481 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312482 MockWrite(
12483 "GET / HTTP/1.1\r\n"
12484 "Host: www.example.org\r\n"
12485 "Connection: keep-alive\r\n"
12486 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712487 };
12488
12489 // Lastly, the server responds with the actual content.
12490 MockRead data_reads2[] = {
12491 MockRead("HTTP/1.1 200 OK\r\n"),
12492 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12493 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612494 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712495 };
12496
Ryan Sleevib8d7ea02018-05-07 20:01:0112497 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712498 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912499 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712500
[email protected]49639fa2011-12-20 23:22:4112501 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712502
bnc691fda62016-08-12 00:43:1612503 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012504
tfarina42834112016-09-22 13:38:2012505 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112506 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712507
12508 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112509 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712510
bnc691fda62016-08-12 00:43:1612511 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212512 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812513 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712514
[email protected]49639fa2011-12-20 23:22:4112515 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712516
bnc691fda62016-08-12 00:43:1612517 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712519
12520 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112521 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712522
bnc691fda62016-08-12 00:43:1612523 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212524 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812525 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712526 EXPECT_EQ(100, response->headers->GetContentLength());
12527}
12528
12529// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112530TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Nicolas Arciniegad2013f92020-02-07 23:00:5612531 session_deps_.proxy_resolution_service =
12532 ConfiguredProxyResolutionService::CreateFixed(
12533 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712534
12535 HttpRequestInfo request;
12536 request.method = "GET";
bncce36dca22015-04-21 22:11:2312537 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012538 request.traffic_annotation =
12539 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712540
12541 MockRead proxy_reads[] = {
12542 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612543 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712544 };
12545
Ryan Sleevib8d7ea02018-05-07 20:01:0112546 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612547 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712548
[email protected]bb88e1d32013-05-03 23:11:0712549 session_deps_.socket_factory->AddSocketDataProvider(&data);
12550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712551
[email protected]49639fa2011-12-20 23:22:4112552 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712553
[email protected]bb88e1d32013-05-03 23:11:0712554 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712555
danakj1fd259a02016-04-16 03:17:0912556 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612557 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712558
tfarina42834112016-09-22 13:38:2012559 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712561
12562 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112563 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712564}
12565
bncd16676a2016-07-20 16:23:0112566TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612567 HttpRequestInfo request;
12568 request.method = "GET";
bncce36dca22015-04-21 22:11:2312569 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012570 request.traffic_annotation =
12571 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612572
danakj1fd259a02016-04-16 03:17:0912573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612574 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712575
[email protected]e22e1362009-11-23 21:31:1212576 MockRead data_reads[] = {
12577 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612578 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212579 };
[email protected]9492e4a2010-02-24 00:58:4612580
Ryan Sleevib8d7ea02018-05-07 20:01:0112581 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712582 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612583
[email protected]49639fa2011-12-20 23:22:4112584 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612585
tfarina42834112016-09-22 13:38:2012586 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112587 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612588
robpercival214763f2016-07-01 23:27:0112589 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612590
bnc691fda62016-08-12 00:43:1612591 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212592 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612593
wezca1070932016-05-26 20:30:5212594 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612595 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12596
12597 std::string response_data;
bnc691fda62016-08-12 00:43:1612598 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112599 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212600}
12601
bncd16676a2016-07-20 16:23:0112602TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512603 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212604 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412605 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112606 UploadFileElementReader::ScopedOverridingContentLengthForTests
12607 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312608
danakj1fd259a02016-04-16 03:17:0912609 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912610 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412611 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712612 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212613 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712614
12615 HttpRequestInfo request;
12616 request.method = "POST";
bncce36dca22015-04-21 22:11:2312617 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712618 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012619 request.traffic_annotation =
12620 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712621
danakj1fd259a02016-04-16 03:17:0912622 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612623 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312624
12625 MockRead data_reads[] = {
12626 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12627 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612628 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312629 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112630 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712631 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312632
[email protected]49639fa2011-12-20 23:22:4112633 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312634
tfarina42834112016-09-22 13:38:2012635 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112636 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312637
12638 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112639 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312640
bnc691fda62016-08-12 00:43:1612641 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212642 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312643
maksim.sisove869bf52016-06-23 17:11:5212644 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312645
[email protected]dd3aa792013-07-16 19:10:2312646 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3312647}
12648
bncd16676a2016-07-20 16:23:0112649TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512650 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212651 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612652 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812653 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12654 base::WriteFile(temp_file, temp_file_content.c_str(),
12655 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112656 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612657
danakj1fd259a02016-04-16 03:17:0912658 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912659 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412660 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712661 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212662 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712663
12664 HttpRequestInfo request;
12665 request.method = "POST";
bncce36dca22015-04-21 22:11:2312666 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712667 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012668 request.traffic_annotation =
12669 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712670
[email protected]999dd8c2013-11-12 06:45:5412671 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912672 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612673 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612674
Ryan Sleevib8d7ea02018-05-07 20:01:0112675 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712676 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612677
[email protected]49639fa2011-12-20 23:22:4112678 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612679
tfarina42834112016-09-22 13:38:2012680 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112681 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612682
12683 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112684 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612685
[email protected]dd3aa792013-07-16 19:10:2312686 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3612687}
12688
bncd16676a2016-07-20 16:23:0112689TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312690 class FakeUploadElementReader : public UploadElementReader {
12691 public:
Chris Watkins7a41d3552017-12-01 02:13:2712692 FakeUploadElementReader() = default;
12693 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0312694
Matt Menkecc1d3a902018-02-05 18:27:3312695 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0312696
12697 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3312698 int Init(CompletionOnceCallback callback) override {
12699 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0312700 return ERR_IO_PENDING;
12701 }
avibf0746c2015-12-09 19:53:1412702 uint64_t GetContentLength() const override { return 0; }
12703 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2012704 int Read(IOBuffer* buf,
12705 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3312706 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0312707 return ERR_FAILED;
12708 }
12709
12710 private:
Matt Menkecc1d3a902018-02-05 18:27:3312711 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0312712 };
12713
12714 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0912715 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12716 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2212717 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0312718
12719 HttpRequestInfo request;
12720 request.method = "POST";
bncce36dca22015-04-21 22:11:2312721 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0312722 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1012723 request.traffic_annotation =
12724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0312725
danakj1fd259a02016-04-16 03:17:0912726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812727 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912728 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0312729
12730 StaticSocketDataProvider data;
12731 session_deps_.socket_factory->AddSocketDataProvider(&data);
12732
12733 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2012734 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112735 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5512736 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0312737
12738 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3312739 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
12740 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0312741
12742 // Return Init()'s result after the transaction gets destroyed.
12743 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3312744 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0312745}
12746
[email protected]aeefc9e82010-02-19 16:18:2712747// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0112748TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2712749 HttpRequestInfo request;
12750 request.method = "GET";
bncce36dca22015-04-21 22:11:2312751 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012752 request.traffic_annotation =
12753 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2712754
12755 // First transaction will request a resource and receive a Basic challenge
12756 // with realm="first_realm".
12757 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312758 MockWrite(
12759 "GET / HTTP/1.1\r\n"
12760 "Host: www.example.org\r\n"
12761 "Connection: keep-alive\r\n"
12762 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712763 };
12764 MockRead data_reads1[] = {
12765 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12766 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12767 "\r\n"),
12768 };
12769
bnc691fda62016-08-12 00:43:1612770 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2712771 // for first_realm. The server will reject and provide a challenge with
12772 // second_realm.
12773 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312774 MockWrite(
12775 "GET / HTTP/1.1\r\n"
12776 "Host: www.example.org\r\n"
12777 "Connection: keep-alive\r\n"
12778 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
12779 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712780 };
12781 MockRead data_reads2[] = {
12782 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12783 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
12784 "\r\n"),
12785 };
12786
12787 // This again fails, and goes back to first_realm. Make sure that the
12788 // entry is removed from cache.
12789 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2312790 MockWrite(
12791 "GET / HTTP/1.1\r\n"
12792 "Host: www.example.org\r\n"
12793 "Connection: keep-alive\r\n"
12794 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
12795 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712796 };
12797 MockRead data_reads3[] = {
12798 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12799 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12800 "\r\n"),
12801 };
12802
12803 // Try one last time (with the correct password) and get the resource.
12804 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312805 MockWrite(
12806 "GET / HTTP/1.1\r\n"
12807 "Host: www.example.org\r\n"
12808 "Connection: keep-alive\r\n"
12809 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12810 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712811 };
12812 MockRead data_reads4[] = {
12813 MockRead("HTTP/1.1 200 OK\r\n"
12814 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012815 "Content-Length: 5\r\n"
12816 "\r\n"
12817 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712818 };
12819
Ryan Sleevib8d7ea02018-05-07 20:01:0112820 StaticSocketDataProvider data1(data_reads1, data_writes1);
12821 StaticSocketDataProvider data2(data_reads2, data_writes2);
12822 StaticSocketDataProvider data3(data_reads3, data_writes3);
12823 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712824 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12825 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12826 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12827 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712828
[email protected]49639fa2011-12-20 23:22:4112829 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712830
danakj1fd259a02016-04-16 03:17:0912831 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612832 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012833
[email protected]aeefc9e82010-02-19 16:18:2712834 // Issue the first request with Authorize headers. There should be a
12835 // password prompt for first_realm waiting to be filled in after the
12836 // transaction completes.
tfarina42834112016-09-22 13:38:2012837 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712839 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112840 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612841 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212842 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812843 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212844 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412845 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312846 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412847 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912848 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712849
12850 // Issue the second request with an incorrect password. There should be a
12851 // password prompt for second_realm waiting to be filled in after the
12852 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112853 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612854 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12855 callback2.callback());
robpercival214763f2016-07-01 23:27:0112856 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712857 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112858 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612859 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212860 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812861 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212862 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412863 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312864 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412865 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912866 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712867
12868 // Issue the third request with another incorrect password. There should be
12869 // a password prompt for first_realm waiting to be filled in. If the password
12870 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12871 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112872 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612873 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12874 callback3.callback());
robpercival214763f2016-07-01 23:27:0112875 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712876 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112877 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612878 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212879 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812880 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212881 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412882 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312883 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412884 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912885 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712886
12887 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112888 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612889 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12890 callback4.callback());
robpercival214763f2016-07-01 23:27:0112891 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712892 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112893 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612894 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212895 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812896 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712897}
12898
Bence Béky230ac612017-08-30 19:17:0812899// Regression test for https://crbug.com/754395.
12900TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12901 MockRead data_reads[] = {
12902 MockRead("HTTP/1.1 200 OK\r\n"),
12903 MockRead(kAlternativeServiceHttpHeader),
12904 MockRead("\r\n"),
12905 MockRead("hello world"),
12906 MockRead(SYNCHRONOUS, OK),
12907 };
12908
12909 HttpRequestInfo request;
12910 request.method = "GET";
12911 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012912 request.traffic_annotation =
12913 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812914
Ryan Sleevib8d7ea02018-05-07 20:01:0112915 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812916 session_deps_.socket_factory->AddSocketDataProvider(&data);
12917
12918 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912919 ssl.ssl_info.cert =
12920 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12921 ASSERT_TRUE(ssl.ssl_info.cert);
12922 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12924
12925 TestCompletionCallback callback;
12926
12927 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12928 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12929
12930 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12932
12933 url::SchemeHostPort test_server(request.url);
12934 HttpServerProperties* http_server_properties =
12935 session->http_server_properties();
12936 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912937 http_server_properties
12938 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12939 .empty());
Bence Béky230ac612017-08-30 19:17:0812940
12941 EXPECT_THAT(callback.WaitForResult(), IsOk());
12942
12943 const HttpResponseInfo* response = trans.GetResponseInfo();
12944 ASSERT_TRUE(response);
12945 ASSERT_TRUE(response->headers);
12946 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12947 EXPECT_FALSE(response->was_fetched_via_spdy);
12948 EXPECT_FALSE(response->was_alpn_negotiated);
12949
12950 std::string response_data;
12951 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12952 EXPECT_EQ("hello world", response_data);
12953
12954 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912955 http_server_properties
12956 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12957 .empty());
Bence Béky230ac612017-08-30 19:17:0812958}
12959
bncd16676a2016-07-20 16:23:0112960TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212961 MockRead data_reads[] = {
12962 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312963 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212964 MockRead("\r\n"),
12965 MockRead("hello world"),
12966 MockRead(SYNCHRONOUS, OK),
12967 };
12968
12969 HttpRequestInfo request;
12970 request.method = "GET";
bncb26024382016-06-29 02:39:4512971 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012972 request.traffic_annotation =
12973 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212974
Ryan Sleevib8d7ea02018-05-07 20:01:0112975 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212976 session_deps_.socket_factory->AddSocketDataProvider(&data);
12977
bncb26024382016-06-29 02:39:4512978 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912979 ssl.ssl_info.cert =
12980 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12981 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512982 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12983
bncc958faa2015-07-31 18:14:5212984 TestCompletionCallback callback;
12985
danakj1fd259a02016-04-16 03:17:0912986 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612987 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212988
tfarina42834112016-09-22 13:38:2012989 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112990 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212991
bncb26024382016-06-29 02:39:4512992 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012993 HttpServerProperties* http_server_properties =
12994 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412995 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912996 http_server_properties
12997 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12998 .empty());
bncc958faa2015-07-31 18:14:5212999
robpercival214763f2016-07-01 23:27:0113000 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213001
bnc691fda62016-08-12 00:43:1613002 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213003 ASSERT_TRUE(response);
13004 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213005 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13006 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213007 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213008
13009 std::string response_data;
bnc691fda62016-08-12 00:43:1613010 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213011 EXPECT_EQ("hello world", response_data);
13012
zhongyic4de03032017-05-19 04:07:3413013 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913014 http_server_properties->GetAlternativeServiceInfos(test_server,
13015 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413016 ASSERT_EQ(1u, alternative_service_info_vector.size());
13017 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13018 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413019 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5213020}
13021
Matt Menke3233d8f22019-08-20 21:01:4913022TEST_F(HttpNetworkTransactionTest,
13023 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
13024 base::test::ScopedFeatureList feature_list;
13025 feature_list.InitWithFeatures(
13026 // enabled_features
13027 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
13028 // Need to partition connections by NetworkIsolationKey for
13029 // SpdySessionKeys to include NetworkIsolationKeys.
13030 features::kPartitionConnectionsByNetworkIsolationKey},
13031 // disabled_features
13032 {});
13033 // Since HttpServerProperties caches the feature value, have to create a new
13034 // one.
13035 session_deps_.http_server_properties =
13036 std::make_unique<HttpServerProperties>();
13037
13038 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
13039 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
13040 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
13041 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
13042
13043 MockRead data_reads[] = {
13044 MockRead("HTTP/1.1 200 OK\r\n"),
13045 MockRead(kAlternativeServiceHttpHeader),
13046 MockRead("\r\n"),
13047 MockRead("hello world"),
13048 MockRead(SYNCHRONOUS, OK),
13049 };
13050
13051 HttpRequestInfo request;
13052 request.method = "GET";
13053 request.url = GURL("https://www.example.org/");
13054 request.traffic_annotation =
13055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13056 request.network_isolation_key = kNetworkIsolationKey1;
13057
13058 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
13059 session_deps_.socket_factory->AddSocketDataProvider(&data);
13060
13061 SSLSocketDataProvider ssl(ASYNC, OK);
13062 ssl.ssl_info.cert =
13063 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13064 ASSERT_TRUE(ssl.ssl_info.cert);
13065 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13066
13067 TestCompletionCallback callback;
13068
13069 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13070 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13071
13072 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13074
13075 url::SchemeHostPort test_server(request.url);
13076 HttpServerProperties* http_server_properties =
13077 session->http_server_properties();
13078 EXPECT_TRUE(
13079 http_server_properties
13080 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
13081 .empty());
13082
13083 EXPECT_THAT(callback.WaitForResult(), IsOk());
13084
13085 const HttpResponseInfo* response = trans.GetResponseInfo();
13086 ASSERT_TRUE(response);
13087 ASSERT_TRUE(response->headers);
13088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13089 EXPECT_FALSE(response->was_fetched_via_spdy);
13090 EXPECT_FALSE(response->was_alpn_negotiated);
13091
13092 std::string response_data;
13093 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13094 EXPECT_EQ("hello world", response_data);
13095
13096 AlternativeServiceInfoVector alternative_service_info_vector =
13097 http_server_properties->GetAlternativeServiceInfos(test_server,
13098 kNetworkIsolationKey1);
13099 ASSERT_EQ(1u, alternative_service_info_vector.size());
13100 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13101 EXPECT_EQ(alternative_service,
13102 alternative_service_info_vector[0].alternative_service());
13103
13104 // Make sure the alternative service information is only associated with
13105 // kNetworkIsolationKey1.
13106 EXPECT_TRUE(
13107 http_server_properties
13108 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13109 .empty());
13110 EXPECT_TRUE(
13111 http_server_properties
13112 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13113 .empty());
13114}
13115
bnce3dd56f2016-06-01 10:37:1113116// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113117TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113118 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113119 MockRead data_reads[] = {
13120 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313121 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113122 MockRead("\r\n"),
13123 MockRead("hello world"),
13124 MockRead(SYNCHRONOUS, OK),
13125 };
13126
13127 HttpRequestInfo request;
13128 request.method = "GET";
13129 request.url = GURL("http://www.example.org/");
13130 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013131 request.traffic_annotation =
13132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113133
Ryan Sleevib8d7ea02018-05-07 20:01:0113134 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113135 session_deps_.socket_factory->AddSocketDataProvider(&data);
13136
13137 TestCompletionCallback callback;
13138
13139 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613140 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113141
13142 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013143 HttpServerProperties* http_server_properties =
13144 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413145 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913146 http_server_properties
13147 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13148 .empty());
bnce3dd56f2016-06-01 10:37:1113149
tfarina42834112016-09-22 13:38:2013150 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13152 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113153
bnc691fda62016-08-12 00:43:1613154 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113155 ASSERT_TRUE(response);
13156 ASSERT_TRUE(response->headers);
13157 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13158 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213159 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113160
13161 std::string response_data;
bnc691fda62016-08-12 00:43:1613162 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113163 EXPECT_EQ("hello world", response_data);
13164
zhongyic4de03032017-05-19 04:07:3413165 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913166 http_server_properties
13167 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13168 .empty());
bnce3dd56f2016-06-01 10:37:1113169}
13170
bnca86731e2017-04-17 12:31:2813171// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513172// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113173TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513174 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813175 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513176
bnc8bef8da22016-05-30 01:28:2513177 HttpRequestInfo request;
13178 request.method = "GET";
bncb26024382016-06-29 02:39:4513179 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513180 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013181 request.traffic_annotation =
13182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513183
13184 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13185 StaticSocketDataProvider first_data;
13186 first_data.set_connect_data(mock_connect);
13187 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513188 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613189 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513190 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513191
13192 MockRead data_reads[] = {
13193 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13194 MockRead(ASYNC, OK),
13195 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113196 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513197 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13198
13199 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13200
bnc525e175a2016-06-20 12:36:4013201 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513202 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113203 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13204 444);
bnc8bef8da22016-05-30 01:28:2513205 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113206 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713207 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13208 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513209
bnc691fda62016-08-12 00:43:1613210 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513211 TestCompletionCallback callback;
13212
tfarina42834112016-09-22 13:38:2013213 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513214 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113215 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513216}
13217
bnce3dd56f2016-06-01 10:37:1113218// Regression test for https://crbug.com/615497:
13219// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113220TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113221 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113222 HttpRequestInfo request;
13223 request.method = "GET";
13224 request.url = GURL("http://www.example.org/");
13225 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013226 request.traffic_annotation =
13227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113228
13229 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13230 StaticSocketDataProvider first_data;
13231 first_data.set_connect_data(mock_connect);
13232 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13233
13234 MockRead data_reads[] = {
13235 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13236 MockRead(ASYNC, OK),
13237 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113238 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113239 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13240
13241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13242
bnc525e175a2016-06-20 12:36:4013243 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113244 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113245 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113246 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113247 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713248 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13249 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113250
bnc691fda62016-08-12 00:43:1613251 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113252 TestCompletionCallback callback;
13253
tfarina42834112016-09-22 13:38:2013254 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113255 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113256 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113257}
13258
bncd16676a2016-07-20 16:23:0113259TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813260 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913261 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013262 HttpServerProperties* http_server_properties =
13263 session->http_server_properties();
bncb26024382016-06-29 02:39:4513264 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113265 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813266 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113267 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713268 test_server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813269 session->context().quic_context->params()->supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913270 EXPECT_EQ(1u,
13271 http_server_properties
13272 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13273 .size());
bnc4f575852015-10-14 18:35:0813274
13275 // Send a clear header.
13276 MockRead data_reads[] = {
13277 MockRead("HTTP/1.1 200 OK\r\n"),
13278 MockRead("Alt-Svc: clear\r\n"),
13279 MockRead("\r\n"),
13280 MockRead("hello world"),
13281 MockRead(SYNCHRONOUS, OK),
13282 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113283 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813284 session_deps_.socket_factory->AddSocketDataProvider(&data);
13285
bncb26024382016-06-29 02:39:4513286 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913287 ssl.ssl_info.cert =
13288 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13289 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13291
bnc4f575852015-10-14 18:35:0813292 HttpRequestInfo request;
13293 request.method = "GET";
bncb26024382016-06-29 02:39:4513294 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013295 request.traffic_annotation =
13296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813297
13298 TestCompletionCallback callback;
13299
bnc691fda62016-08-12 00:43:1613300 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813301
tfarina42834112016-09-22 13:38:2013302 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113303 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813304
bnc691fda62016-08-12 00:43:1613305 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213306 ASSERT_TRUE(response);
13307 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813308 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13309 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213310 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813311
13312 std::string response_data;
bnc691fda62016-08-12 00:43:1613313 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813314 EXPECT_EQ("hello world", response_data);
13315
zhongyic4de03032017-05-19 04:07:3413316 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913317 http_server_properties
13318 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13319 .empty());
bnc4f575852015-10-14 18:35:0813320}
13321
bncd16676a2016-07-20 16:23:0113322TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213323 MockRead data_reads[] = {
13324 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313325 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13326 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213327 MockRead("hello world"),
13328 MockRead(SYNCHRONOUS, OK),
13329 };
13330
13331 HttpRequestInfo request;
13332 request.method = "GET";
bncb26024382016-06-29 02:39:4513333 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013334 request.traffic_annotation =
13335 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213336
Ryan Sleevib8d7ea02018-05-07 20:01:0113337 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213338 session_deps_.socket_factory->AddSocketDataProvider(&data);
13339
bncb26024382016-06-29 02:39:4513340 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913341 ssl.ssl_info.cert =
13342 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13343 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513344 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13345
bncc958faa2015-07-31 18:14:5213346 TestCompletionCallback callback;
13347
danakj1fd259a02016-04-16 03:17:0913348 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613349 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213350
tfarina42834112016-09-22 13:38:2013351 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113352 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213353
bncb26024382016-06-29 02:39:4513354 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013355 HttpServerProperties* http_server_properties =
13356 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413357 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913358 http_server_properties
13359 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13360 .empty());
bncc958faa2015-07-31 18:14:5213361
robpercival214763f2016-07-01 23:27:0113362 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213363
bnc691fda62016-08-12 00:43:1613364 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213365 ASSERT_TRUE(response);
13366 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213367 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13368 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213369 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213370
13371 std::string response_data;
bnc691fda62016-08-12 00:43:1613372 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213373 EXPECT_EQ("hello world", response_data);
13374
zhongyic4de03032017-05-19 04:07:3413375 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913376 http_server_properties->GetAlternativeServiceInfos(test_server,
13377 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413378 ASSERT_EQ(2u, alternative_service_info_vector.size());
13379
13380 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13381 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413382 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413383 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13384 1234);
13385 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413386 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213387}
13388
bncd16676a2016-07-20 16:23:0113389TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613390 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213391 HostPortPair alternative("alternative.example.org", 443);
13392 std::string origin_url = "https://origin.example.org:443";
13393 std::string alternative_url = "https://alternative.example.org:443";
13394
13395 // Negotiate HTTP/1.1 with alternative.example.org.
13396 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613397 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13399
13400 // HTTP/1.1 data for request.
13401 MockWrite http_writes[] = {
13402 MockWrite("GET / HTTP/1.1\r\n"
13403 "Host: alternative.example.org\r\n"
13404 "Connection: keep-alive\r\n\r\n"),
13405 };
13406
13407 MockRead http_reads[] = {
13408 MockRead("HTTP/1.1 200 OK\r\n"
13409 "Content-Type: text/html; charset=iso-8859-1\r\n"
13410 "Content-Length: 40\r\n\r\n"
13411 "first HTTP/1.1 response from alternative"),
13412 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113413 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213414 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13415
13416 StaticSocketDataProvider data_refused;
13417 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13418 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13419
zhongyi3d4a55e72016-04-22 20:36:4613420 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913421 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013422 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213423 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113424 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213425 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113426 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713427 server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813428 DefaultSupportedQuicVersions());
zhongyi48704c182015-12-07 07:52:0213429 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513430 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13431 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213432
zhongyi48704c182015-12-07 07:52:0213433 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613434 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213435 request.method = "GET";
13436 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013437 request.traffic_annotation =
13438 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13439
zhongyi48704c182015-12-07 07:52:0213440 TestCompletionCallback callback;
13441 NetErrorDetails details;
13442 EXPECT_FALSE(details.quic_broken);
13443
tfarina42834112016-09-22 13:38:2013444 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613445 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213446 EXPECT_TRUE(details.quic_broken);
13447}
13448
bncd16676a2016-07-20 16:23:0113449TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613450 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213451 HostPortPair alternative1("alternative1.example.org", 443);
13452 HostPortPair alternative2("alternative2.example.org", 443);
13453 std::string origin_url = "https://origin.example.org:443";
13454 std::string alternative_url1 = "https://alternative1.example.org:443";
13455 std::string alternative_url2 = "https://alternative2.example.org:443";
13456
13457 // Negotiate HTTP/1.1 with alternative1.example.org.
13458 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613459 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13461
13462 // HTTP/1.1 data for request.
13463 MockWrite http_writes[] = {
13464 MockWrite("GET / HTTP/1.1\r\n"
13465 "Host: alternative1.example.org\r\n"
13466 "Connection: keep-alive\r\n\r\n"),
13467 };
13468
13469 MockRead http_reads[] = {
13470 MockRead("HTTP/1.1 200 OK\r\n"
13471 "Content-Type: text/html; charset=iso-8859-1\r\n"
13472 "Content-Length: 40\r\n\r\n"
13473 "first HTTP/1.1 response from alternative1"),
13474 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113475 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213476 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13477
13478 StaticSocketDataProvider data_refused;
13479 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13480 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13481
danakj1fd259a02016-04-16 03:17:0913482 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013483 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213484 session->http_server_properties();
13485
zhongyi3d4a55e72016-04-22 20:36:4613486 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213487 AlternativeServiceInfoVector alternative_service_info_vector;
13488 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13489
bnc3472afd2016-11-17 15:27:2113490 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113491 alternative_service_info_vector.push_back(
13492 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13493 alternative_service1, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813494 session->context().quic_context->params()->supported_versions));
bnc3472afd2016-11-17 15:27:2113495 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113496 alternative_service_info_vector.push_back(
13497 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13498 alternative_service2, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813499 session->context().quic_context->params()->supported_versions));
zhongyi48704c182015-12-07 07:52:0213500
13501 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913502 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213503
13504 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513505 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13506 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913507 EXPECT_EQ(2u, http_server_properties
13508 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13509 .size());
zhongyi48704c182015-12-07 07:52:0213510
zhongyi48704c182015-12-07 07:52:0213511 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613512 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213513 request.method = "GET";
13514 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1013515 request.traffic_annotation =
13516 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13517
zhongyi48704c182015-12-07 07:52:0213518 TestCompletionCallback callback;
13519 NetErrorDetails details;
13520 EXPECT_FALSE(details.quic_broken);
13521
tfarina42834112016-09-22 13:38:2013522 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613523 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213524 EXPECT_FALSE(details.quic_broken);
13525}
13526
bncd16676a2016-07-20 16:23:0113527TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213528 HttpRequestInfo request;
13529 request.method = "GET";
bncb26024382016-06-29 02:39:4513530 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013531 request.traffic_annotation =
13532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213533
[email protected]d973e99a2012-02-17 21:02:3613534 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213535 StaticSocketDataProvider first_data;
13536 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713537 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513538 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613539 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513540 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213541
13542 MockRead data_reads[] = {
13543 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13544 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613545 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213546 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113547 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713548 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213549
danakj1fd259a02016-04-16 03:17:0913550 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213551
bnc525e175a2016-06-20 12:36:4013552 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313553 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613554 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113555 // Port must be < 1024, or the header will be ignored (since initial port was
13556 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113557 // Port is ignored by MockConnect anyway.
13558 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13559 666);
bnc7dc7e1b42015-07-28 14:43:1213560 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113561 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713562 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213563
bnc691fda62016-08-12 00:43:1613564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113565 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213566
tfarina42834112016-09-22 13:38:2013567 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113568 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13569 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213570
bnc691fda62016-08-12 00:43:1613571 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213572 ASSERT_TRUE(response);
13573 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213574 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13575
13576 std::string response_data;
bnc691fda62016-08-12 00:43:1613577 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213578 EXPECT_EQ("hello world", response_data);
13579
zhongyic4de03032017-05-19 04:07:3413580 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913581 http_server_properties->GetAlternativeServiceInfos(server,
13582 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413583 ASSERT_EQ(1u, alternative_service_info_vector.size());
13584 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413585 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513586 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13587 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213588}
13589
bnc55ff9da2015-08-19 18:42:3513590// Ensure that we are not allowed to redirect traffic via an alternate protocol
13591// to an unrestricted (port >= 1024) when the original traffic was on a
13592// restricted port (port < 1024). Ensure that we can redirect in all other
13593// cases.
bncd16676a2016-07-20 16:23:0113594TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113595 HttpRequestInfo restricted_port_request;
13596 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513597 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113598 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013599 restricted_port_request.traffic_annotation =
13600 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113601
[email protected]d973e99a2012-02-17 21:02:3613602 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113603 StaticSocketDataProvider first_data;
13604 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713605 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113606
13607 MockRead data_reads[] = {
13608 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13609 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613610 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113611 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113612 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713613 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513614 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613615 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513616 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113617
danakj1fd259a02016-04-16 03:17:0913618 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113619
bnc525e175a2016-06-20 12:36:4013620 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313621 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113622 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113623 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13624 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213625 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113626 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713627 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13628 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113629
bnc691fda62016-08-12 00:43:1613630 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113631 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113632
tfarina42834112016-09-22 13:38:2013633 int rv = trans.Start(&restricted_port_request, callback.callback(),
13634 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113635 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113636 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113637 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913638}
[email protected]3912662a32011-10-04 00:51:1113639
bnc55ff9da2015-08-19 18:42:3513640// Ensure that we are allowed to redirect traffic via an alternate protocol to
13641// an unrestricted (port >= 1024) when the original traffic was on a restricted
13642// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113643TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713644 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913645
13646 HttpRequestInfo restricted_port_request;
13647 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513648 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913649 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013650 restricted_port_request.traffic_annotation =
13651 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913652
13653 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13654 StaticSocketDataProvider first_data;
13655 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713656 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913657
13658 MockRead data_reads[] = {
13659 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13660 MockRead("hello world"),
13661 MockRead(ASYNC, OK),
13662 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113663 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713664 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513665 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613666 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513667 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913668
danakj1fd259a02016-04-16 03:17:0913669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913670
bnc525e175a2016-06-20 12:36:4013671 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913672 session->http_server_properties();
13673 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113674 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13675 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213676 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113677 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713678 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13679 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913680
bnc691fda62016-08-12 00:43:1613681 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913682 TestCompletionCallback callback;
13683
tfarina42834112016-09-22 13:38:2013684 EXPECT_EQ(ERR_IO_PENDING,
13685 trans.Start(&restricted_port_request, callback.callback(),
13686 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913687 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113688 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113689}
13690
bnc55ff9da2015-08-19 18:42:3513691// Ensure that we are not allowed to redirect traffic via an alternate protocol
13692// to an unrestricted (port >= 1024) when the original traffic was on a
13693// restricted port (port < 1024). Ensure that we can redirect in all other
13694// cases.
bncd16676a2016-07-20 16:23:0113695TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1113696 HttpRequestInfo restricted_port_request;
13697 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513698 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113699 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013700 restricted_port_request.traffic_annotation =
13701 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113702
[email protected]d973e99a2012-02-17 21:02:3613703 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113704 StaticSocketDataProvider first_data;
13705 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713706 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113707
13708 MockRead data_reads[] = {
13709 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13710 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613711 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113712 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113713 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713714 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113715
bncb26024382016-06-29 02:39:4513716 SSLSocketDataProvider ssl(ASYNC, OK);
13717 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13718
danakj1fd259a02016-04-16 03:17:0913719 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113720
bnc525e175a2016-06-20 12:36:4013721 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313722 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113723 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113724 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13725 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213726 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113727 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713728 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13729 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113730
bnc691fda62016-08-12 00:43:1613731 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113732 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113733
tfarina42834112016-09-22 13:38:2013734 int rv = trans.Start(&restricted_port_request, callback.callback(),
13735 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113736 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113737 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113738 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113739}
13740
bnc55ff9da2015-08-19 18:42:3513741// Ensure that we are not allowed to redirect traffic via an alternate protocol
13742// to an unrestricted (port >= 1024) when the original traffic was on a
13743// restricted port (port < 1024). Ensure that we can redirect in all other
13744// cases.
bncd16676a2016-07-20 16:23:0113745TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1113746 HttpRequestInfo unrestricted_port_request;
13747 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513748 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113749 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013750 unrestricted_port_request.traffic_annotation =
13751 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113752
[email protected]d973e99a2012-02-17 21:02:3613753 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113754 StaticSocketDataProvider first_data;
13755 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713756 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113757
13758 MockRead data_reads[] = {
13759 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13760 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613761 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113762 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113763 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713764 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513765 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613766 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513767 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113768
danakj1fd259a02016-04-16 03:17:0913769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113770
bnc525e175a2016-06-20 12:36:4013771 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313772 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113773 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113774 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13775 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213776 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113777 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713778 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13779 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113780
bnc691fda62016-08-12 00:43:1613781 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113782 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113783
bnc691fda62016-08-12 00:43:1613784 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013785 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113786 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113787 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113788 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113789}
13790
bnc55ff9da2015-08-19 18:42:3513791// Ensure that we are not allowed to redirect traffic via an alternate protocol
13792// to an unrestricted (port >= 1024) when the original traffic was on a
13793// restricted port (port < 1024). Ensure that we can redirect in all other
13794// cases.
bncd16676a2016-07-20 16:23:0113795TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113796 HttpRequestInfo unrestricted_port_request;
13797 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513798 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113799 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013800 unrestricted_port_request.traffic_annotation =
13801 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113802
[email protected]d973e99a2012-02-17 21:02:3613803 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113804 StaticSocketDataProvider first_data;
13805 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713806 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113807
13808 MockRead data_reads[] = {
13809 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13810 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613811 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113812 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113813 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713814 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113815
bncb26024382016-06-29 02:39:4513816 SSLSocketDataProvider ssl(ASYNC, OK);
13817 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13818
danakj1fd259a02016-04-16 03:17:0913819 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113820
bnc525e175a2016-06-20 12:36:4013821 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313822 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213823 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113824 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13825 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213826 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113827 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713828 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13829 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113830
bnc691fda62016-08-12 00:43:1613831 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113832 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113833
bnc691fda62016-08-12 00:43:1613834 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013835 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113837 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113838 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113839}
13840
bnc55ff9da2015-08-19 18:42:3513841// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113842// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13843// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113844TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213845 HttpRequestInfo request;
13846 request.method = "GET";
bncce36dca22015-04-21 22:11:2313847 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013848 request.traffic_annotation =
13849 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213850
13851 // The alternate protocol request will error out before we attempt to connect,
13852 // so only the standard HTTP request will try to connect.
13853 MockRead data_reads[] = {
13854 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13855 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613856 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213857 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113858 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713859 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213860
danakj1fd259a02016-04-16 03:17:0913861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213862
bnc525e175a2016-06-20 12:36:4013863 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213864 session->http_server_properties();
13865 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113866 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13867 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213868 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113869 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713870 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13871 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213872
bnc691fda62016-08-12 00:43:1613873 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213874 TestCompletionCallback callback;
13875
tfarina42834112016-09-22 13:38:2013876 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213878 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113879 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213880
bnc691fda62016-08-12 00:43:1613881 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213882 ASSERT_TRUE(response);
13883 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213884 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13885
13886 std::string response_data;
bnc691fda62016-08-12 00:43:1613887 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213888 EXPECT_EQ("hello world", response_data);
13889}
13890
bncd16676a2016-07-20 16:23:0113891TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413892 HttpRequestInfo request;
13893 request.method = "GET";
bncb26024382016-06-29 02:39:4513894 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013895 request.traffic_annotation =
13896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413897
13898 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213899 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313900 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213901 MockRead("\r\n"),
13902 MockRead("hello world"),
13903 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13904 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413905
Ryan Sleevib8d7ea02018-05-07 20:01:0113906 StaticSocketDataProvider first_transaction(data_reads,
13907 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713908 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513909 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613910 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513911 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413912
bnc032658ba2016-09-26 18:17:1513913 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413914
Ryan Hamilton0239aac2018-05-19 00:03:1313915 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513916 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113917 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413918
Raul Tambre94493c652019-03-11 17:18:3513919 spdy::SpdySerializedFrame resp(
13920 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313921 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413922 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113923 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413924 };
13925
Ryan Sleevib8d7ea02018-05-07 20:01:0113926 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713927 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413928
[email protected]d973e99a2012-02-17 21:02:3613929 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113930 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513931 hanging_non_alternate_protocol_socket.set_connect_data(
13932 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713933 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513934 &hanging_non_alternate_protocol_socket);
13935
[email protected]49639fa2011-12-20 23:22:4113936 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413937
danakj1fd259a02016-04-16 03:17:0913938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813939 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913940 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413941
tfarina42834112016-09-22 13:38:2013942 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13944 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413945
13946 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213947 ASSERT_TRUE(response);
13948 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413949 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13950
13951 std::string response_data;
robpercival214763f2016-07-01 23:27:0113952 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413953 EXPECT_EQ("hello world", response_data);
13954
bnc87dcefc2017-05-25 12:47:5813955 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913956 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413957
tfarina42834112016-09-22 13:38:2013958 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13960 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413961
13962 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213963 ASSERT_TRUE(response);
13964 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213965 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313966 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213967 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413968
robpercival214763f2016-07-01 23:27:0113969 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413970 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413971}
13972
bncd16676a2016-07-20 16:23:0113973TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513974 HttpRequestInfo request;
13975 request.method = "GET";
bncb26024382016-06-29 02:39:4513976 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013977 request.traffic_annotation =
13978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513979
bncb26024382016-06-29 02:39:4513980 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513981 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213982 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313983 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213984 MockRead("\r\n"),
13985 MockRead("hello world"),
13986 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13987 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513988 };
13989
Ryan Sleevib8d7ea02018-05-07 20:01:0113990 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513991 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513992
bncb26024382016-06-29 02:39:4513993 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913994 ssl_http11.ssl_info.cert =
13995 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13996 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513997 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13998
13999 // Second transaction starts an alternative and a non-alternative Job.
14000 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3614001 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114002 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1814003 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1814004 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
14005
Ryan Sleevib8d7ea02018-05-07 20:01:0114006 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1814007 hanging_socket2.set_connect_data(never_finishing_connect);
14008 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5514009
bncb26024382016-06-29 02:39:4514010 // Third transaction starts an alternative and a non-alternative job.
14011 // The non-alternative job hangs, but the alternative one succeeds.
14012 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1314013 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4514014 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1314015 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4514016 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5514017 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4114018 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5514019 };
Raul Tambre94493c652019-03-11 17:18:3514020 spdy::SpdySerializedFrame resp1(
14021 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314022 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3514023 spdy::SpdySerializedFrame resp2(
14024 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1314025 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5514026 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114027 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
14028 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1314029 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5514030 };
14031
Ryan Sleevib8d7ea02018-05-07 20:01:0114032 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714033 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5514034
bnc032658ba2016-09-26 18:17:1514035 AddSSLSocketData();
bncb26024382016-06-29 02:39:4514036
Ryan Sleevib8d7ea02018-05-07 20:01:0114037 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1814038 hanging_socket3.set_connect_data(never_finishing_connect);
14039 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5514040
danakj1fd259a02016-04-16 03:17:0914041 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4114042 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5014043 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514044
tfarina42834112016-09-22 13:38:2014045 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114046 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14047 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514048
14049 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5214050 ASSERT_TRUE(response);
14051 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514052 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14053
14054 std::string response_data;
robpercival214763f2016-07-01 23:27:0114055 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514056 EXPECT_EQ("hello world", response_data);
14057
[email protected]49639fa2011-12-20 23:22:4114058 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5014059 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014060 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114061 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514062
[email protected]49639fa2011-12-20 23:22:4114063 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5014064 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014065 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114066 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514067
robpercival214763f2016-07-01 23:27:0114068 EXPECT_THAT(callback2.WaitForResult(), IsOk());
14069 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514070
14071 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5214072 ASSERT_TRUE(response);
14073 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214074 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514075 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214076 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114077 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514078 EXPECT_EQ("hello!", response_data);
14079
14080 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5214081 ASSERT_TRUE(response);
14082 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214083 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514084 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214085 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114086 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514087 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5514088}
14089
bncd16676a2016-07-20 16:23:0114090TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5314091 session_deps_.host_resolver->set_synchronous_mode(true);
14092
[email protected]2d6728692011-03-12 01:39:5514093 HttpRequestInfo request;
14094 request.method = "GET";
bncb26024382016-06-29 02:39:4514095 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014096 request.traffic_annotation =
14097 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514098
14099 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214100 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314101 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214102 MockRead("\r\n"),
14103 MockRead("hello world"),
14104 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14105 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514106 };
14107
Ryan Sleevib8d7ea02018-05-07 20:01:0114108 StaticSocketDataProvider first_transaction(data_reads,
14109 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714110 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5514111
[email protected]8ddf8322012-02-23 18:08:0614112 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914113 ssl.ssl_info.cert =
14114 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14115 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714116 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514117
[email protected]d973e99a2012-02-17 21:02:3614118 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114119 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514120 hanging_alternate_protocol_socket.set_connect_data(
14121 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714122 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514123 &hanging_alternate_protocol_socket);
14124
bncb26024382016-06-29 02:39:4514125 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114126 StaticSocketDataProvider second_transaction(data_reads,
14127 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814128 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514129 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514130
[email protected]49639fa2011-12-20 23:22:4114131 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514132
danakj1fd259a02016-04-16 03:17:0914133 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814134 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914135 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514136
tfarina42834112016-09-22 13:38:2014137 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14139 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514140
14141 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214142 ASSERT_TRUE(response);
14143 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514144 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14145
14146 std::string response_data;
robpercival214763f2016-07-01 23:27:0114147 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514148 EXPECT_EQ("hello world", response_data);
14149
bnc87dcefc2017-05-25 12:47:5814150 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914151 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514152
tfarina42834112016-09-22 13:38:2014153 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114154 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14155 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514156
14157 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214158 ASSERT_TRUE(response);
14159 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514160 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14161 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214162 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514163
robpercival214763f2016-07-01 23:27:0114164 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514165 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514166}
14167
bnc2e884782016-08-11 19:45:1914168// Test that proxy is resolved using the origin url,
14169// regardless of the alternative server.
14170TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14171 // Configure proxy to bypass www.example.org, which is the origin URL.
14172 ProxyConfig proxy_config;
14173 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14174 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914175 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14176 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914177
14178 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914179 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914180 &capturing_proxy_resolver);
14181
Matt Muellerd9342e3a2019-11-26 01:41:1414182 RecordingTestNetLog net_log;
bnc2e884782016-08-11 19:45:1914183
Bence Béky53a5aef2018-03-29 21:54:1214184 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614185 std::make_unique<ConfiguredProxyResolutionService>(
Bence Béky53a5aef2018-03-29 21:54:1214186 std::move(proxy_config_service), std::move(proxy_resolver_factory),
Eric Roman3be01ba2020-04-03 21:37:0914187 &net_log, /*quick_check_enabled=*/true);
bnc2e884782016-08-11 19:45:1914188
14189 session_deps_.net_log = &net_log;
14190
14191 // Configure alternative service with a hostname that is not bypassed by the
14192 // proxy.
14193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14194 HttpServerProperties* http_server_properties =
14195 session->http_server_properties();
14196 url::SchemeHostPort server("https", "www.example.org", 443);
14197 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114198 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914199 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114200 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714201 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914202
14203 // Non-alternative job should hang.
14204 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114205 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914206 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14207 session_deps_.socket_factory->AddSocketDataProvider(
14208 &hanging_alternate_protocol_socket);
14209
bnc032658ba2016-09-26 18:17:1514210 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914211
14212 HttpRequestInfo request;
14213 request.method = "GET";
14214 request.url = GURL("https://www.example.org/");
14215 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1014216 request.traffic_annotation =
14217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914218
Ryan Hamilton0239aac2018-05-19 00:03:1314219 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914220 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14221
14222 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14223
Ryan Hamilton0239aac2018-05-19 00:03:1314224 spdy::SpdySerializedFrame resp(
14225 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14226 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914227 MockRead spdy_reads[] = {
14228 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14229 };
14230
Ryan Sleevib8d7ea02018-05-07 20:01:0114231 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914232 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14233
14234 TestCompletionCallback callback;
14235
14236 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14237
tfarina42834112016-09-22 13:38:2014238 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914239 EXPECT_THAT(callback.GetResult(rv), IsOk());
14240
14241 const HttpResponseInfo* response = trans.GetResponseInfo();
14242 ASSERT_TRUE(response);
14243 ASSERT_TRUE(response->headers);
14244 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14245 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214246 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914247
14248 std::string response_data;
14249 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14250 EXPECT_EQ("hello!", response_data);
14251
14252 // Origin host bypasses proxy, no resolution should have happened.
Matt Menke8045afd2019-11-14 20:31:1914253 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
bnc2e884782016-08-11 19:45:1914254}
14255
bncd16676a2016-07-20 16:23:0114256TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114257 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214258 proxy_config.set_auto_detect(true);
14259 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114260
sammc5dd160c2015-04-02 02:43:1314261 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914262 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614263 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4914264 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14265 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14266 std::make_unique<CapturingProxyResolverFactory>(
14267 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:0914268 nullptr, /*quick_check_enabled=*/true);
Matt Muellerd9342e3a2019-11-26 01:41:1414269 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714270 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114271
14272 HttpRequestInfo request;
14273 request.method = "GET";
bncb26024382016-06-29 02:39:4514274 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014275 request.traffic_annotation =
14276 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114277
14278 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214279 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314280 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214281 MockRead("\r\n"),
14282 MockRead("hello world"),
14283 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14284 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114285 };
14286
Ryan Sleevib8d7ea02018-05-07 20:01:0114287 StaticSocketDataProvider first_transaction(data_reads,
14288 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714289 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514290 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614291 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514292 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114293
bnc032658ba2016-09-26 18:17:1514294 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114295
Ryan Hamilton0239aac2018-05-19 00:03:1314296 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514297 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114298 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314299 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514300 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14301 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314302 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114303 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114304 };
14305
[email protected]d911f1b2010-05-05 22:39:4214306 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14307
Raul Tambre94493c652019-03-11 17:18:3514308 spdy::SpdySerializedFrame resp(
14309 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314310 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114311 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114312 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14313 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114314 };
14315
Ryan Sleevib8d7ea02018-05-07 20:01:0114316 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714317 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114318
[email protected]d973e99a2012-02-17 21:02:3614319 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114320 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514321 hanging_non_alternate_protocol_socket.set_connect_data(
14322 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714323 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514324 &hanging_non_alternate_protocol_socket);
14325
[email protected]49639fa2011-12-20 23:22:4114326 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114327
danakj1fd259a02016-04-16 03:17:0914328 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814329 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914330 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114331
tfarina42834112016-09-22 13:38:2014332 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14334 EXPECT_THAT(callback.WaitForResult(), IsOk());
14335
14336 const HttpResponseInfo* response = trans->GetResponseInfo();
14337 ASSERT_TRUE(response);
14338 ASSERT_TRUE(response->headers);
14339 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14340 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214341 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114342
14343 std::string response_data;
14344 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14345 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114346
bnc87dcefc2017-05-25 12:47:5814347 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914348 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114349
tfarina42834112016-09-22 13:38:2014350 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114351 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14352 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114353
mmenkea2dcd3bf2016-08-16 21:49:4114354 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214355 ASSERT_TRUE(response);
14356 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214357 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314358 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214359 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114360
robpercival214763f2016-07-01 23:27:0114361 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114362 EXPECT_EQ("hello!", response_data);
Matt Menke8045afd2019-11-14 20:31:1914363 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
bncb26024382016-06-29 02:39:4514364 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914365 capturing_proxy_resolver.lookup_info()[0].url.spec());
bncce36dca22015-04-21 22:11:2314366 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914367 capturing_proxy_resolver.lookup_info()[1].url.spec());
[email protected]631f1322010-04-30 17:59:1114368
[email protected]029c83b62013-01-24 05:28:2014369 LoadTimingInfo load_timing_info;
14370 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14371 TestLoadTimingNotReusedWithPac(load_timing_info,
14372 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114373}
[email protected]631f1322010-04-30 17:59:1114374
bncd16676a2016-07-20 16:23:0114375TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814376 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414377 HttpRequestInfo request;
14378 request.method = "GET";
bncb26024382016-06-29 02:39:4514379 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014380 request.traffic_annotation =
14381 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414382
14383 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214384 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314385 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214386 MockRead("\r\n"),
14387 MockRead("hello world"),
14388 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414389 };
14390
Ryan Sleevib8d7ea02018-05-07 20:01:0114391 StaticSocketDataProvider first_transaction(data_reads,
14392 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714393 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514394 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614395 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514396 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414397
bnc032658ba2016-09-26 18:17:1514398 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414399
Ryan Hamilton0239aac2018-05-19 00:03:1314400 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514401 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114402 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414403
Raul Tambre94493c652019-03-11 17:18:3514404 spdy::SpdySerializedFrame resp(
14405 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314406 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414407 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114408 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414409 };
14410
Ryan Sleevib8d7ea02018-05-07 20:01:0114411 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714412 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414413
[email protected]83039bb2011-12-09 18:43:5514414 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414415
danakj1fd259a02016-04-16 03:17:0914416 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414417
bnc87dcefc2017-05-25 12:47:5814418 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914419 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414420
tfarina42834112016-09-22 13:38:2014421 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114422 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14423 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414424
14425 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214426 ASSERT_TRUE(response);
14427 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414428 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14429
14430 std::string response_data;
robpercival214763f2016-07-01 23:27:0114431 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414432 EXPECT_EQ("hello world", response_data);
14433
14434 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514435 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014436 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114437 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414438 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14439 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714440 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214441 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814442
bnc87dcefc2017-05-25 12:47:5814443 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914444 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414445
tfarina42834112016-09-22 13:38:2014446 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114447 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14448 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414449
14450 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214451 ASSERT_TRUE(response);
14452 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214453 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314454 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214455 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414456
robpercival214763f2016-07-01 23:27:0114457 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414458 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214459}
14460
[email protected]044de0642010-06-17 10:42:1514461// GenerateAuthToken is a mighty big test.
14462// It tests all permutation of GenerateAuthToken behavior:
14463// - Synchronous and Asynchronous completion.
14464// - OK or error on completion.
14465// - Direct connection, non-authenticating proxy, and authenticating proxy.
14466// - HTTP or HTTPS backend (to include proxy tunneling).
14467// - Non-authenticating and authenticating backend.
14468//
[email protected]fe3b7dc2012-02-03 19:52:0914469// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514470// problems generating an auth token for an authenticating proxy, we don't
14471// need to test all permutations of the backend server).
14472//
14473// The test proceeds by going over each of the configuration cases, and
14474// potentially running up to three rounds in each of the tests. The TestConfig
14475// specifies both the configuration for the test as well as the expectations
14476// for the results.
bncd16676a2016-07-20 16:23:0114477TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014478 static const char kServer[] = "http://www.example.com";
14479 static const char kSecureServer[] = "https://www.example.com";
14480 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514481
14482 enum AuthTiming {
14483 AUTH_NONE,
14484 AUTH_SYNC,
14485 AUTH_ASYNC,
14486 };
14487
14488 const MockWrite kGet(
14489 "GET / HTTP/1.1\r\n"
14490 "Host: www.example.com\r\n"
14491 "Connection: keep-alive\r\n\r\n");
14492 const MockWrite kGetProxy(
14493 "GET http://www.example.com/ HTTP/1.1\r\n"
14494 "Host: www.example.com\r\n"
14495 "Proxy-Connection: keep-alive\r\n\r\n");
14496 const MockWrite kGetAuth(
14497 "GET / HTTP/1.1\r\n"
14498 "Host: www.example.com\r\n"
14499 "Connection: keep-alive\r\n"
14500 "Authorization: auth_token\r\n\r\n");
14501 const MockWrite kGetProxyAuth(
14502 "GET http://www.example.com/ HTTP/1.1\r\n"
14503 "Host: www.example.com\r\n"
14504 "Proxy-Connection: keep-alive\r\n"
14505 "Proxy-Authorization: auth_token\r\n\r\n");
14506 const MockWrite kGetAuthThroughProxy(
14507 "GET http://www.example.com/ HTTP/1.1\r\n"
14508 "Host: www.example.com\r\n"
14509 "Proxy-Connection: keep-alive\r\n"
14510 "Authorization: auth_token\r\n\r\n");
14511 const MockWrite kGetAuthWithProxyAuth(
14512 "GET http://www.example.com/ HTTP/1.1\r\n"
14513 "Host: www.example.com\r\n"
14514 "Proxy-Connection: keep-alive\r\n"
14515 "Proxy-Authorization: auth_token\r\n"
14516 "Authorization: auth_token\r\n\r\n");
14517 const MockWrite kConnect(
14518 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714519 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514520 "Proxy-Connection: keep-alive\r\n\r\n");
14521 const MockWrite kConnectProxyAuth(
14522 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714523 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514524 "Proxy-Connection: keep-alive\r\n"
14525 "Proxy-Authorization: auth_token\r\n\r\n");
14526
14527 const MockRead kSuccess(
14528 "HTTP/1.1 200 OK\r\n"
14529 "Content-Type: text/html; charset=iso-8859-1\r\n"
14530 "Content-Length: 3\r\n\r\n"
14531 "Yes");
14532 const MockRead kFailure(
14533 "Should not be called.");
14534 const MockRead kServerChallenge(
14535 "HTTP/1.1 401 Unauthorized\r\n"
14536 "WWW-Authenticate: Mock realm=server\r\n"
14537 "Content-Type: text/html; charset=iso-8859-1\r\n"
14538 "Content-Length: 14\r\n\r\n"
14539 "Unauthorized\r\n");
14540 const MockRead kProxyChallenge(
14541 "HTTP/1.1 407 Unauthorized\r\n"
14542 "Proxy-Authenticate: Mock realm=proxy\r\n"
14543 "Proxy-Connection: close\r\n"
14544 "Content-Type: text/html; charset=iso-8859-1\r\n"
14545 "Content-Length: 14\r\n\r\n"
14546 "Unauthorized\r\n");
14547 const MockRead kProxyConnected(
14548 "HTTP/1.1 200 Connection Established\r\n\r\n");
14549
14550 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14551 // no constructors, but the C++ compiler on Windows warns about
14552 // unspecified data in compound literals. So, moved to using constructors,
14553 // and TestRound's created with the default constructor should not be used.
14554 struct TestRound {
14555 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514556 : expected_rv(ERR_UNEXPECTED),
14557 extra_write(nullptr),
14558 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314559 TestRound(const MockWrite& write_arg,
14560 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514561 int expected_rv_arg)
14562 : write(write_arg),
14563 read(read_arg),
14564 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514565 extra_write(nullptr),
14566 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514567 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14568 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114569 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514570 : write(write_arg),
14571 read(read_arg),
14572 expected_rv(expected_rv_arg),
14573 extra_write(extra_write_arg),
14574 extra_read(extra_read_arg) {
14575 }
14576 MockWrite write;
14577 MockRead read;
14578 int expected_rv;
14579 const MockWrite* extra_write;
14580 const MockRead* extra_read;
14581 };
14582
14583 static const int kNoSSL = 500;
14584
14585 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114586 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114587 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514588 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114589 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114590 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514591 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114592 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514593 int num_auth_rounds;
14594 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614595 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514596 } test_configs[] = {
asankac93076192016-10-03 15:46:0214597 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114598 {__LINE__,
14599 nullptr,
asankac93076192016-10-03 15:46:0214600 AUTH_NONE,
14601 OK,
14602 kServer,
14603 AUTH_NONE,
14604 OK,
14605 1,
14606 kNoSSL,
14607 {TestRound(kGet, kSuccess, OK)}},
14608 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114609 {__LINE__,
14610 nullptr,
asankac93076192016-10-03 15:46:0214611 AUTH_NONE,
14612 OK,
14613 kServer,
14614 AUTH_SYNC,
14615 OK,
14616 2,
14617 kNoSSL,
14618 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514619 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114620 {__LINE__,
14621 nullptr,
asankac93076192016-10-03 15:46:0214622 AUTH_NONE,
14623 OK,
14624 kServer,
14625 AUTH_SYNC,
14626 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614627 3,
14628 kNoSSL,
14629 {TestRound(kGet, kServerChallenge, OK),
14630 TestRound(kGet, kServerChallenge, OK),
14631 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114632 {__LINE__,
14633 nullptr,
asankae2257db2016-10-11 22:03:1614634 AUTH_NONE,
14635 OK,
14636 kServer,
14637 AUTH_SYNC,
14638 ERR_UNSUPPORTED_AUTH_SCHEME,
14639 2,
14640 kNoSSL,
14641 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114642 {__LINE__,
14643 nullptr,
asankae2257db2016-10-11 22:03:1614644 AUTH_NONE,
14645 OK,
14646 kServer,
14647 AUTH_SYNC,
14648 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14649 2,
14650 kNoSSL,
14651 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114652 {__LINE__,
14653 kProxy,
asankae2257db2016-10-11 22:03:1614654 AUTH_SYNC,
14655 ERR_FAILED,
14656 kServer,
14657 AUTH_NONE,
14658 OK,
14659 2,
14660 kNoSSL,
14661 {TestRound(kGetProxy, kProxyChallenge, OK),
14662 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114663 {__LINE__,
14664 kProxy,
asankae2257db2016-10-11 22:03:1614665 AUTH_ASYNC,
14666 ERR_FAILED,
14667 kServer,
14668 AUTH_NONE,
14669 OK,
14670 2,
14671 kNoSSL,
14672 {TestRound(kGetProxy, kProxyChallenge, OK),
14673 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114674 {__LINE__,
14675 nullptr,
asankae2257db2016-10-11 22:03:1614676 AUTH_NONE,
14677 OK,
14678 kServer,
14679 AUTH_SYNC,
14680 ERR_FAILED,
asankac93076192016-10-03 15:46:0214681 2,
14682 kNoSSL,
14683 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614684 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114685 {__LINE__,
14686 nullptr,
asankae2257db2016-10-11 22:03:1614687 AUTH_NONE,
14688 OK,
14689 kServer,
14690 AUTH_ASYNC,
14691 ERR_FAILED,
14692 2,
14693 kNoSSL,
14694 {TestRound(kGet, kServerChallenge, OK),
14695 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114696 {__LINE__,
14697 nullptr,
asankac93076192016-10-03 15:46:0214698 AUTH_NONE,
14699 OK,
14700 kServer,
14701 AUTH_ASYNC,
14702 OK,
14703 2,
14704 kNoSSL,
14705 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514706 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114707 {__LINE__,
14708 nullptr,
asankac93076192016-10-03 15:46:0214709 AUTH_NONE,
14710 OK,
14711 kServer,
14712 AUTH_ASYNC,
14713 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614714 3,
asankac93076192016-10-03 15:46:0214715 kNoSSL,
14716 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614717 // The second round uses a HttpAuthHandlerMock that always succeeds.
14718 TestRound(kGet, kServerChallenge, OK),
14719 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214720 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114721 {__LINE__,
14722 kProxy,
asankac93076192016-10-03 15:46:0214723 AUTH_NONE,
14724 OK,
14725 kServer,
14726 AUTH_NONE,
14727 OK,
14728 1,
14729 kNoSSL,
14730 {TestRound(kGetProxy, kSuccess, OK)}},
14731 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114732 {__LINE__,
14733 kProxy,
asankac93076192016-10-03 15:46:0214734 AUTH_NONE,
14735 OK,
14736 kServer,
14737 AUTH_SYNC,
14738 OK,
14739 2,
14740 kNoSSL,
14741 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514742 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114743 {__LINE__,
14744 kProxy,
asankac93076192016-10-03 15:46:0214745 AUTH_NONE,
14746 OK,
14747 kServer,
14748 AUTH_SYNC,
14749 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614750 3,
asankac93076192016-10-03 15:46:0214751 kNoSSL,
14752 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614753 TestRound(kGetProxy, kServerChallenge, OK),
14754 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114755 {__LINE__,
14756 kProxy,
asankac93076192016-10-03 15:46:0214757 AUTH_NONE,
14758 OK,
14759 kServer,
14760 AUTH_ASYNC,
14761 OK,
14762 2,
14763 kNoSSL,
14764 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514765 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114766 {__LINE__,
14767 kProxy,
asankac93076192016-10-03 15:46:0214768 AUTH_NONE,
14769 OK,
14770 kServer,
14771 AUTH_ASYNC,
14772 ERR_INVALID_AUTH_CREDENTIALS,
14773 2,
14774 kNoSSL,
14775 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614776 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214777 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114778 {__LINE__,
14779 kProxy,
asankac93076192016-10-03 15:46:0214780 AUTH_SYNC,
14781 OK,
14782 kServer,
14783 AUTH_NONE,
14784 OK,
14785 2,
14786 kNoSSL,
14787 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514788 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114789 {__LINE__,
14790 kProxy,
asankac93076192016-10-03 15:46:0214791 AUTH_SYNC,
14792 ERR_INVALID_AUTH_CREDENTIALS,
14793 kServer,
14794 AUTH_NONE,
14795 OK,
14796 2,
14797 kNoSSL,
14798 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614799 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114800 {__LINE__,
14801 kProxy,
asankac93076192016-10-03 15:46:0214802 AUTH_ASYNC,
14803 OK,
14804 kServer,
14805 AUTH_NONE,
14806 OK,
14807 2,
14808 kNoSSL,
14809 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514810 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114811 {__LINE__,
14812 kProxy,
asankac93076192016-10-03 15:46:0214813 AUTH_ASYNC,
14814 ERR_INVALID_AUTH_CREDENTIALS,
14815 kServer,
14816 AUTH_NONE,
14817 OK,
14818 2,
14819 kNoSSL,
14820 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614821 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114822 {__LINE__,
14823 kProxy,
14824 AUTH_ASYNC,
14825 ERR_INVALID_AUTH_CREDENTIALS,
14826 kServer,
14827 AUTH_NONE,
14828 OK,
14829 3,
14830 kNoSSL,
14831 {TestRound(kGetProxy, kProxyChallenge, OK),
14832 TestRound(kGetProxy, kProxyChallenge, OK),
14833 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214834 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114835 {__LINE__,
14836 kProxy,
asankac93076192016-10-03 15:46:0214837 AUTH_SYNC,
14838 OK,
14839 kServer,
14840 AUTH_SYNC,
14841 OK,
14842 3,
14843 kNoSSL,
14844 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514845 TestRound(kGetProxyAuth, kServerChallenge, OK),
14846 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114847 {__LINE__,
14848 kProxy,
asankac93076192016-10-03 15:46:0214849 AUTH_SYNC,
14850 OK,
14851 kServer,
14852 AUTH_SYNC,
14853 ERR_INVALID_AUTH_CREDENTIALS,
14854 3,
14855 kNoSSL,
14856 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514857 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614858 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114859 {__LINE__,
14860 kProxy,
asankac93076192016-10-03 15:46:0214861 AUTH_ASYNC,
14862 OK,
14863 kServer,
14864 AUTH_SYNC,
14865 OK,
14866 3,
14867 kNoSSL,
14868 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514869 TestRound(kGetProxyAuth, kServerChallenge, OK),
14870 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114871 {__LINE__,
14872 kProxy,
asankac93076192016-10-03 15:46:0214873 AUTH_ASYNC,
14874 OK,
14875 kServer,
14876 AUTH_SYNC,
14877 ERR_INVALID_AUTH_CREDENTIALS,
14878 3,
14879 kNoSSL,
14880 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514881 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614882 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114883 {__LINE__,
14884 kProxy,
asankac93076192016-10-03 15:46:0214885 AUTH_SYNC,
14886 OK,
14887 kServer,
14888 AUTH_ASYNC,
14889 OK,
14890 3,
14891 kNoSSL,
14892 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514893 TestRound(kGetProxyAuth, kServerChallenge, OK),
14894 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114895 {__LINE__,
14896 kProxy,
14897 AUTH_SYNC,
14898 ERR_INVALID_AUTH_CREDENTIALS,
14899 kServer,
14900 AUTH_ASYNC,
14901 OK,
14902 4,
14903 kNoSSL,
14904 {TestRound(kGetProxy, kProxyChallenge, OK),
14905 TestRound(kGetProxy, kProxyChallenge, OK),
14906 TestRound(kGetProxyAuth, kServerChallenge, OK),
14907 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14908 {__LINE__,
14909 kProxy,
asankac93076192016-10-03 15:46:0214910 AUTH_SYNC,
14911 OK,
14912 kServer,
14913 AUTH_ASYNC,
14914 ERR_INVALID_AUTH_CREDENTIALS,
14915 3,
14916 kNoSSL,
14917 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514918 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614919 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114920 {__LINE__,
14921 kProxy,
asankac93076192016-10-03 15:46:0214922 AUTH_ASYNC,
14923 OK,
14924 kServer,
14925 AUTH_ASYNC,
14926 OK,
14927 3,
14928 kNoSSL,
14929 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514930 TestRound(kGetProxyAuth, kServerChallenge, OK),
14931 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114932 {__LINE__,
14933 kProxy,
asankac93076192016-10-03 15:46:0214934 AUTH_ASYNC,
14935 OK,
14936 kServer,
14937 AUTH_ASYNC,
14938 ERR_INVALID_AUTH_CREDENTIALS,
14939 3,
14940 kNoSSL,
14941 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514942 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614943 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114944 {__LINE__,
14945 kProxy,
14946 AUTH_ASYNC,
14947 ERR_INVALID_AUTH_CREDENTIALS,
14948 kServer,
14949 AUTH_ASYNC,
14950 ERR_INVALID_AUTH_CREDENTIALS,
14951 4,
14952 kNoSSL,
14953 {TestRound(kGetProxy, kProxyChallenge, OK),
14954 TestRound(kGetProxy, kProxyChallenge, OK),
14955 TestRound(kGetProxyAuth, kServerChallenge, OK),
14956 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214957 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114958 {__LINE__,
14959 nullptr,
asankac93076192016-10-03 15:46:0214960 AUTH_NONE,
14961 OK,
14962 kSecureServer,
14963 AUTH_NONE,
14964 OK,
14965 1,
14966 0,
14967 {TestRound(kGet, kSuccess, OK)}},
14968 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114969 {__LINE__,
14970 nullptr,
asankac93076192016-10-03 15:46:0214971 AUTH_NONE,
14972 OK,
14973 kSecureServer,
14974 AUTH_SYNC,
14975 OK,
14976 2,
14977 0,
14978 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514979 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114980 {__LINE__,
14981 nullptr,
asankac93076192016-10-03 15:46:0214982 AUTH_NONE,
14983 OK,
14984 kSecureServer,
14985 AUTH_SYNC,
14986 ERR_INVALID_AUTH_CREDENTIALS,
14987 2,
14988 0,
asankae2257db2016-10-11 22:03:1614989 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114990 {__LINE__,
14991 nullptr,
asankac93076192016-10-03 15:46:0214992 AUTH_NONE,
14993 OK,
14994 kSecureServer,
14995 AUTH_ASYNC,
14996 OK,
14997 2,
14998 0,
14999 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515000 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115001 {__LINE__,
15002 nullptr,
asankac93076192016-10-03 15:46:0215003 AUTH_NONE,
15004 OK,
15005 kSecureServer,
15006 AUTH_ASYNC,
15007 ERR_INVALID_AUTH_CREDENTIALS,
15008 2,
15009 0,
asankae2257db2016-10-11 22:03:1615010 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215011 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115012 {__LINE__,
15013 kProxy,
asankac93076192016-10-03 15:46:0215014 AUTH_NONE,
15015 OK,
15016 kSecureServer,
15017 AUTH_NONE,
15018 OK,
15019 1,
15020 0,
15021 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
15022 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115023 {__LINE__,
15024 kProxy,
asankac93076192016-10-03 15:46:0215025 AUTH_NONE,
15026 OK,
15027 kSecureServer,
15028 AUTH_SYNC,
15029 OK,
15030 2,
15031 0,
15032 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515033 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115034 {__LINE__,
15035 kProxy,
asankac93076192016-10-03 15:46:0215036 AUTH_NONE,
15037 OK,
15038 kSecureServer,
15039 AUTH_SYNC,
15040 ERR_INVALID_AUTH_CREDENTIALS,
15041 2,
15042 0,
15043 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615044 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115045 {__LINE__,
15046 kProxy,
asankac93076192016-10-03 15:46:0215047 AUTH_NONE,
15048 OK,
15049 kSecureServer,
15050 AUTH_ASYNC,
15051 OK,
15052 2,
15053 0,
15054 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515055 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115056 {__LINE__,
15057 kProxy,
asankac93076192016-10-03 15:46:0215058 AUTH_NONE,
15059 OK,
15060 kSecureServer,
15061 AUTH_ASYNC,
15062 ERR_INVALID_AUTH_CREDENTIALS,
15063 2,
15064 0,
15065 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615066 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215067 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115068 {__LINE__,
15069 kProxy,
asankac93076192016-10-03 15:46:0215070 AUTH_SYNC,
15071 OK,
15072 kSecureServer,
15073 AUTH_NONE,
15074 OK,
15075 2,
15076 1,
15077 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515078 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115079 {__LINE__,
15080 kProxy,
asankac93076192016-10-03 15:46:0215081 AUTH_SYNC,
15082 ERR_INVALID_AUTH_CREDENTIALS,
15083 kSecureServer,
15084 AUTH_NONE,
15085 OK,
15086 2,
15087 kNoSSL,
15088 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615089 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115090 {__LINE__,
15091 kProxy,
asankae2257db2016-10-11 22:03:1615092 AUTH_SYNC,
15093 ERR_UNSUPPORTED_AUTH_SCHEME,
15094 kSecureServer,
15095 AUTH_NONE,
15096 OK,
15097 2,
15098 kNoSSL,
15099 {TestRound(kConnect, kProxyChallenge, OK),
15100 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115101 {__LINE__,
15102 kProxy,
asankae2257db2016-10-11 22:03:1615103 AUTH_SYNC,
15104 ERR_UNEXPECTED,
15105 kSecureServer,
15106 AUTH_NONE,
15107 OK,
15108 2,
15109 kNoSSL,
15110 {TestRound(kConnect, kProxyChallenge, OK),
15111 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115112 {__LINE__,
15113 kProxy,
asankac93076192016-10-03 15:46:0215114 AUTH_ASYNC,
15115 OK,
15116 kSecureServer,
15117 AUTH_NONE,
15118 OK,
15119 2,
15120 1,
15121 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515122 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115123 {__LINE__,
15124 kProxy,
asankac93076192016-10-03 15:46:0215125 AUTH_ASYNC,
15126 ERR_INVALID_AUTH_CREDENTIALS,
15127 kSecureServer,
15128 AUTH_NONE,
15129 OK,
15130 2,
15131 kNoSSL,
15132 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615133 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215134 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115135 {__LINE__,
15136 kProxy,
asankac93076192016-10-03 15:46:0215137 AUTH_SYNC,
15138 OK,
15139 kSecureServer,
15140 AUTH_SYNC,
15141 OK,
15142 3,
15143 1,
15144 {TestRound(kConnect, kProxyChallenge, OK),
15145 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15146 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515147 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115148 {__LINE__,
15149 kProxy,
asankac93076192016-10-03 15:46:0215150 AUTH_SYNC,
15151 OK,
15152 kSecureServer,
15153 AUTH_SYNC,
15154 ERR_INVALID_AUTH_CREDENTIALS,
15155 3,
15156 1,
15157 {TestRound(kConnect, kProxyChallenge, OK),
15158 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15159 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615160 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115161 {__LINE__,
15162 kProxy,
asankac93076192016-10-03 15:46:0215163 AUTH_ASYNC,
15164 OK,
15165 kSecureServer,
15166 AUTH_SYNC,
15167 OK,
15168 3,
15169 1,
15170 {TestRound(kConnect, kProxyChallenge, OK),
15171 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15172 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515173 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115174 {__LINE__,
15175 kProxy,
asankac93076192016-10-03 15:46:0215176 AUTH_ASYNC,
15177 OK,
15178 kSecureServer,
15179 AUTH_SYNC,
15180 ERR_INVALID_AUTH_CREDENTIALS,
15181 3,
15182 1,
15183 {TestRound(kConnect, kProxyChallenge, OK),
15184 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15185 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615186 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115187 {__LINE__,
15188 kProxy,
asankac93076192016-10-03 15:46:0215189 AUTH_SYNC,
15190 OK,
15191 kSecureServer,
15192 AUTH_ASYNC,
15193 OK,
15194 3,
15195 1,
15196 {TestRound(kConnect, kProxyChallenge, OK),
15197 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15198 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515199 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115200 {__LINE__,
15201 kProxy,
asankac93076192016-10-03 15:46:0215202 AUTH_SYNC,
15203 OK,
15204 kSecureServer,
15205 AUTH_ASYNC,
15206 ERR_INVALID_AUTH_CREDENTIALS,
15207 3,
15208 1,
15209 {TestRound(kConnect, kProxyChallenge, OK),
15210 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15211 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615212 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115213 {__LINE__,
15214 kProxy,
asankac93076192016-10-03 15:46:0215215 AUTH_ASYNC,
15216 OK,
15217 kSecureServer,
15218 AUTH_ASYNC,
15219 OK,
15220 3,
15221 1,
15222 {TestRound(kConnect, kProxyChallenge, OK),
15223 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15224 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515225 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115226 {__LINE__,
15227 kProxy,
asankac93076192016-10-03 15:46:0215228 AUTH_ASYNC,
15229 OK,
15230 kSecureServer,
15231 AUTH_ASYNC,
15232 ERR_INVALID_AUTH_CREDENTIALS,
15233 3,
15234 1,
15235 {TestRound(kConnect, kProxyChallenge, OK),
15236 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15237 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615238 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115239 {__LINE__,
15240 kProxy,
15241 AUTH_ASYNC,
15242 ERR_INVALID_AUTH_CREDENTIALS,
15243 kSecureServer,
15244 AUTH_ASYNC,
15245 ERR_INVALID_AUTH_CREDENTIALS,
15246 4,
15247 2,
15248 {TestRound(kConnect, kProxyChallenge, OK),
15249 TestRound(kConnect, kProxyChallenge, OK),
15250 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15251 &kServerChallenge),
15252 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515253 };
15254
asanka463ca4262016-11-16 02:34:3115255 for (const auto& test_config : test_configs) {
15256 SCOPED_TRACE(::testing::Message() << "Test config at "
15257 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815258 HttpAuthHandlerMock::Factory* auth_factory(
15259 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715260 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915261 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615262
15263 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515264 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115265 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815266 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15267 std::string auth_challenge = "Mock realm=proxy";
15268 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415269 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15270 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815271 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
Matt Menke618134b2020-05-22 02:12:2715272 empty_ssl_info, NetworkIsolationKey(),
15273 origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815274 auth_handler->SetGenerateExpectation(
15275 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115276 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815277 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15278 }
[email protected]044de0642010-06-17 10:42:1515279 }
15280 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015281 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515282 std::string auth_challenge = "Mock realm=server";
15283 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415284 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15285 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515286 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715287 empty_ssl_info, NetworkIsolationKey(),
15288 origin, NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515289 auth_handler->SetGenerateExpectation(
15290 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115291 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815292 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615293
15294 // The second handler always succeeds. It should only be used where there
15295 // are multiple auth sessions for server auth in the same network
15296 // transaction using the same auth scheme.
15297 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915298 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615299 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715300 empty_ssl_info, NetworkIsolationKey(),
15301 origin, NetLogWithSource());
asankae2257db2016-10-11 22:03:1615302 second_handler->SetGenerateExpectation(true, OK);
15303 auth_factory->AddMockHandler(second_handler.release(),
15304 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515305 }
15306 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915307 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615308 ConfiguredProxyResolutionService::CreateFixed(
15309 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515310 } else {
Bence Béky53a5aef2018-03-29 21:54:1215311 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615312 ConfiguredProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515313 }
15314
15315 HttpRequestInfo request;
15316 request.method = "GET";
15317 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1015318 request.traffic_annotation =
15319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515320
danakj1fd259a02016-04-16 03:17:0915321 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515322
rchcb68dc62015-05-21 04:45:3615323 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15324
15325 std::vector<std::vector<MockRead>> mock_reads(1);
15326 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515327 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215328 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515329 const TestRound& read_write_round = test_config.rounds[round];
15330
15331 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615332 mock_reads.back().push_back(read_write_round.read);
15333 mock_writes.back().push_back(read_write_round.write);
15334
15335 // kProxyChallenge uses Proxy-Connection: close which means that the
15336 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415337 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615338 mock_reads.push_back(std::vector<MockRead>());
15339 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515340 }
15341
rchcb68dc62015-05-21 04:45:3615342 if (read_write_round.extra_read) {
15343 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515344 }
rchcb68dc62015-05-21 04:45:3615345 if (read_write_round.extra_write) {
15346 mock_writes.back().push_back(*read_write_round.extra_write);
15347 }
[email protected]044de0642010-06-17 10:42:1515348
15349 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515350 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715351 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515352 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615353 }
[email protected]044de0642010-06-17 10:42:1515354
danakj1fd259a02016-04-16 03:17:0915355 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615356 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915357 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115358 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615359 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215360 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615361 }
15362
mmenkecc2298e2015-12-07 18:20:1815363 // Transaction must be created after DataProviders, so it's destroyed before
15364 // they are as well.
15365 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15366
rchcb68dc62015-05-21 04:45:3615367 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215368 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615369 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515370 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115371 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515372 int rv;
15373 if (round == 0) {
tfarina42834112016-09-22 13:38:2015374 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515375 } else {
[email protected]49639fa2011-12-20 23:22:4115376 rv = trans.RestartWithAuth(
15377 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515378 }
15379 if (rv == ERR_IO_PENDING)
15380 rv = callback.WaitForResult();
15381
15382 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615383 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015384 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515385 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515386 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15387 continue;
15388 }
15389 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815390 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515391 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815392 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615393 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515394 }
15395 }
[email protected]e5ae96a2010-04-14 20:12:4515396 }
15397}
15398
bncd16676a2016-07-20 16:23:0115399TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415400 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415401 HttpAuthHandlerMock::Factory* auth_factory(
15402 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715403 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215404 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615405 ConfiguredProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715406 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415407
15408 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15409 auth_handler->set_connection_based(true);
15410 std::string auth_challenge = "Mock realm=server";
15411 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415412 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15413 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915414 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415415 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715416 empty_ssl_info, NetworkIsolationKey(), origin,
15417 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815418 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415419
[email protected]c871bce92010-07-15 21:51:1415420 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515421 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415422 HttpRequestInfo request;
15423 request.method = "GET";
15424 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1015425 request.traffic_annotation =
15426 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715427
danakj1fd259a02016-04-16 03:17:0915428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015429
15430 // Use a TCP Socket Pool with only one connection per group. This is used
15431 // to validate that the TCP socket is not released to the pool between
15432 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215433 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615434 CommonConnectJobParams common_connect_job_params(
15435 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815436 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915437 50, // Max sockets for pool
15438 1, // Max sockets per group
15439 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615440 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215441 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915442 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015443 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15444 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815445 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015446
bnc691fda62016-08-12 00:43:1615447 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115448 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415449
15450 const MockWrite kGet(
15451 "GET / HTTP/1.1\r\n"
15452 "Host: www.example.com\r\n"
15453 "Connection: keep-alive\r\n\r\n");
15454 const MockWrite kGetAuth(
15455 "GET / HTTP/1.1\r\n"
15456 "Host: www.example.com\r\n"
15457 "Connection: keep-alive\r\n"
15458 "Authorization: auth_token\r\n\r\n");
15459
15460 const MockRead kServerChallenge(
15461 "HTTP/1.1 401 Unauthorized\r\n"
15462 "WWW-Authenticate: Mock realm=server\r\n"
15463 "Content-Type: text/html; charset=iso-8859-1\r\n"
15464 "Content-Length: 14\r\n\r\n"
15465 "Unauthorized\r\n");
15466 const MockRead kSuccess(
15467 "HTTP/1.1 200 OK\r\n"
15468 "Content-Type: text/html; charset=iso-8859-1\r\n"
15469 "Content-Length: 3\r\n\r\n"
15470 "Yes");
15471
15472 MockWrite writes[] = {
15473 // First round
15474 kGet,
15475 // Second round
15476 kGetAuth,
15477 // Third round
15478 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015479 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015480 kGetAuth,
15481 // Competing request
15482 kGet,
[email protected]c871bce92010-07-15 21:51:1415483 };
15484 MockRead reads[] = {
15485 // First round
15486 kServerChallenge,
15487 // Second round
15488 kServerChallenge,
15489 // Third round
[email protected]eca50e122010-09-11 14:03:3015490 kServerChallenge,
15491 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415492 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015493 // Competing response
15494 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415495 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115496 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715497 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415498
Matt Menkef6edce752019-03-19 17:21:5615499 const ClientSocketPool::GroupId kSocketGroup(
15500 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415501 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15502 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015503
15504 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415505 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015506 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415507 if (rv == ERR_IO_PENDING)
15508 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115509 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615510 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215511 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815512 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315513 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115514 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15515 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415516
[email protected]7ef4cbbb2011-02-06 11:19:1015517 // In between rounds, another request comes in for the same domain.
15518 // It should not be able to grab the TCP socket that trans has already
15519 // claimed.
bnc691fda62016-08-12 00:43:1615520 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115521 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015522 rv = trans_compete.Start(&request, callback_compete.callback(),
15523 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115524 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015525 // callback_compete.WaitForResult at this point would stall forever,
15526 // since the HttpNetworkTransaction does not release the request back to
15527 // the pool until after authentication completes.
15528
15529 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415530 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615531 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415532 if (rv == ERR_IO_PENDING)
15533 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115534 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615535 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215536 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815537 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315538 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115539 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15540 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415541
[email protected]7ef4cbbb2011-02-06 11:19:1015542 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415543 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615544 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415545 if (rv == ERR_IO_PENDING)
15546 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115547 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615548 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215549 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815550 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315551 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115552 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15553 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015554
[email protected]7ef4cbbb2011-02-06 11:19:1015555 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015556 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615557 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015558 if (rv == ERR_IO_PENDING)
15559 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115560 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615561 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215562 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815563 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315564 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015565
asanka463ca4262016-11-16 02:34:3115566 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15567 // auth handler should transition to a DONE state in concert with the remote
15568 // server. But that's not something we can test here with a mock handler.
15569 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15570 auth_handler->state());
15571
[email protected]7ef4cbbb2011-02-06 11:19:1015572 // Read the body since the fourth round was successful. This will also
15573 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415574 scoped_refptr<IOBufferWithSize> io_buf =
15575 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615576 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015577 if (rv == ERR_IO_PENDING)
15578 rv = callback.WaitForResult();
15579 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615580 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015581 EXPECT_EQ(0, rv);
15582 // There are still 0 idle sockets, since the trans_compete transaction
15583 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315584 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015585
15586 // The competing request can now finish. Wait for the headers and then
15587 // read the body.
15588 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115589 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615590 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015591 if (rv == ERR_IO_PENDING)
15592 rv = callback.WaitForResult();
15593 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615594 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015595 EXPECT_EQ(0, rv);
15596
15597 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315598 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415599}
15600
[email protected]65041fa2010-05-21 06:56:5315601// This tests the case that a request is issued via http instead of spdy after
15602// npn is negotiated.
bncd16676a2016-07-20 16:23:0115603TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315604 HttpRequestInfo request;
15605 request.method = "GET";
bncce36dca22015-04-21 22:11:2315606 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015607 request.traffic_annotation =
15608 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315609
15610 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315611 MockWrite(
15612 "GET / HTTP/1.1\r\n"
15613 "Host: www.example.org\r\n"
15614 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315615 };
15616
15617 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215618 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315619 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215620 MockRead("\r\n"),
15621 MockRead("hello world"),
15622 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315623 };
15624
[email protected]8ddf8322012-02-23 18:08:0615625 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615626 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315627
[email protected]bb88e1d32013-05-03 23:11:0715628 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315629
Ryan Sleevib8d7ea02018-05-07 20:01:0115630 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715631 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315632
[email protected]49639fa2011-12-20 23:22:4115633 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315634
danakj1fd259a02016-04-16 03:17:0915635 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615636 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315637
tfarina42834112016-09-22 13:38:2015638 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315639
robpercival214763f2016-07-01 23:27:0115640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15641 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315642
bnc691fda62016-08-12 00:43:1615643 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215644 ASSERT_TRUE(response);
15645 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315646 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15647
15648 std::string response_data;
bnc691fda62016-08-12 00:43:1615649 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315650 EXPECT_EQ("hello world", response_data);
15651
15652 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215653 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315654}
[email protected]26ef6582010-06-24 02:30:4715655
bnc55ff9da2015-08-19 18:42:3515656// Simulate the SSL handshake completing with an NPN negotiation followed by an
15657// immediate server closing of the socket.
15658// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115659TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715660 HttpRequestInfo request;
15661 request.method = "GET";
bncce36dca22015-04-21 22:11:2315662 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015663 request.traffic_annotation =
15664 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715665
[email protected]8ddf8322012-02-23 18:08:0615666 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615667 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715668 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715669
Ryan Hamilton0239aac2018-05-19 00:03:1315670 spdy::SpdySerializedFrame req(
15671 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115672 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715673
15674 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615675 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715676 };
15677
Ryan Sleevib8d7ea02018-05-07 20:01:0115678 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715679 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715680
[email protected]49639fa2011-12-20 23:22:4115681 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715682
danakj1fd259a02016-04-16 03:17:0915683 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615684 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715685
tfarina42834112016-09-22 13:38:2015686 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15688 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715689}
[email protected]65d34382010-07-01 18:12:2615690
[email protected]795cbf82013-07-22 09:37:2715691// A subclass of HttpAuthHandlerMock that records the request URL when
15692// it gets it. This is needed since the auth handler may get destroyed
15693// before we get a chance to query it.
15694class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
15695 public:
15696 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
15697
Chris Watkins7a41d3552017-12-01 02:13:2715698 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2715699
15700 protected:
dchengb03027d2014-10-21 12:00:2015701 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
15702 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0915703 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2015704 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2715705 *url_ = request->url;
15706 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0915707 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2715708 }
15709
15710 private:
15711 GURL* url_;
15712};
15713
[email protected]8e6441ca2010-08-19 05:56:3815714// Test that if we cancel the transaction as the connection is completing, that
15715// everything tears down correctly.
bncd16676a2016-07-20 16:23:0115716TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3815717 // Setup everything about the connection to complete synchronously, so that
15718 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
15719 // for is the callback from the HttpStreamRequest.
15720 // Then cancel the transaction.
15721 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3615722 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3815723 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615724 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
15725 MockRead(SYNCHRONOUS, "hello world"),
15726 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3815727 };
15728
[email protected]8e6441ca2010-08-19 05:56:3815729 HttpRequestInfo request;
15730 request.method = "GET";
bncce36dca22015-04-21 22:11:2315731 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015732 request.traffic_annotation =
15733 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3815734
danakj1fd259a02016-04-16 03:17:0915735 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5815736 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1915737 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2715738
Ryan Sleevib8d7ea02018-05-07 20:01:0115739 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3815740 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0715741 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3815742
[email protected]49639fa2011-12-20 23:22:4115743 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3815744
Matt Muellerd9342e3a2019-11-26 01:41:1415745 RecordingBoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4115746 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115747 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3815748 trans.reset(); // Cancel the transaction here.
15749
fdoray92e35a72016-06-10 15:54:5515750 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3015751}
15752
[email protected]ecab6e052014-05-16 14:58:1215753// Test that if a transaction is cancelled after receiving the headers, the
15754// stream is drained properly and added back to the socket pool. The main
15755// purpose of this test is to make sure that an HttpStreamParser can be read
15756// from after the HttpNetworkTransaction and the objects it owns have been
15757// deleted.
15758// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0115759TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1215760 MockRead data_reads[] = {
15761 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
15762 MockRead(ASYNC, "Content-Length: 2\r\n"),
15763 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
15764 MockRead(ASYNC, "1"),
15765 // 2 async reads are necessary to trigger a ReadResponseBody call after the
15766 // HttpNetworkTransaction has been deleted.
15767 MockRead(ASYNC, "2"),
15768 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
15769 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115770 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1215771 session_deps_.socket_factory->AddSocketDataProvider(&data);
15772
danakj1fd259a02016-04-16 03:17:0915773 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1215774
15775 {
15776 HttpRequestInfo request;
15777 request.method = "GET";
bncce36dca22015-04-21 22:11:2315778 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015779 request.traffic_annotation =
15780 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1215781
dcheng48459ac22014-08-26 00:46:4115782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1215783 TestCompletionCallback callback;
15784
tfarina42834112016-09-22 13:38:2015785 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115786 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1215787 callback.WaitForResult();
15788
15789 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215790 ASSERT_TRUE(response);
15791 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1215792 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15793
15794 // The transaction and HttpRequestInfo are deleted.
15795 }
15796
15797 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515798 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215799
15800 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115801 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215802}
15803
[email protected]76a505b2010-08-25 06:23:0015804// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115805TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915806 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615807 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4915808 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1415809 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715810 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915811 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015812
[email protected]76a505b2010-08-25 06:23:0015813 HttpRequestInfo request;
15814 request.method = "GET";
bncce36dca22015-04-21 22:11:2315815 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015816 request.traffic_annotation =
15817 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015818
15819 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315820 MockWrite(
15821 "GET http://www.example.org/ HTTP/1.1\r\n"
15822 "Host: www.example.org\r\n"
15823 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015824 };
15825
15826 MockRead data_reads1[] = {
15827 MockRead("HTTP/1.1 200 OK\r\n"),
15828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15829 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615830 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015831 };
15832
Ryan Sleevib8d7ea02018-05-07 20:01:0115833 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715834 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015835
[email protected]49639fa2011-12-20 23:22:4115836 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015837
bnc691fda62016-08-12 00:43:1615838 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015839
bnc691fda62016-08-12 00:43:1615840 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115841 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015842
15843 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115844 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015845
bnc691fda62016-08-12 00:43:1615846 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215847 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015848
15849 EXPECT_TRUE(response->headers->IsKeepAlive());
15850 EXPECT_EQ(200, response->headers->response_code());
15851 EXPECT_EQ(100, response->headers->GetContentLength());
15852 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715853 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15854 HostPortPair::FromString("myproxy:70")),
15855 response->proxy_server);
[email protected]76a505b2010-08-25 06:23:0015856 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015857
15858 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615859 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015860 TestLoadTimingNotReusedWithPac(load_timing_info,
15861 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015862}
15863
15864// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115865TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915866 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615867 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4915868 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1415869 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715870 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915871 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015872
[email protected]76a505b2010-08-25 06:23:0015873 HttpRequestInfo request;
15874 request.method = "GET";
bncce36dca22015-04-21 22:11:2315875 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015876 request.traffic_annotation =
15877 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015878
15879 // Since we have proxy, should try to establish tunnel.
15880 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715881 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15882 "Host: www.example.org:443\r\n"
15883 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015884
rsleevidb16bb02015-11-12 23:47:1715885 MockWrite("GET / HTTP/1.1\r\n"
15886 "Host: www.example.org\r\n"
15887 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015888 };
15889
15890 MockRead data_reads1[] = {
15891 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15892
15893 MockRead("HTTP/1.1 200 OK\r\n"),
15894 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15895 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615896 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015897 };
15898
Ryan Sleevib8d7ea02018-05-07 20:01:0115899 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715900 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615901 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715902 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015903
[email protected]49639fa2011-12-20 23:22:4115904 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015905
bnc691fda62016-08-12 00:43:1615906 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015907
bnc691fda62016-08-12 00:43:1615908 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115909 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015910
15911 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115912 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415913 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015914 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015915 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15916 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015917 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015918 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015919 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15920 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015921
bnc691fda62016-08-12 00:43:1615922 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215923 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015924
15925 EXPECT_TRUE(response->headers->IsKeepAlive());
15926 EXPECT_EQ(200, response->headers->response_code());
15927 EXPECT_EQ(100, response->headers->GetContentLength());
15928 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15929 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715930 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15931 HostPortPair::FromString("myproxy:70")),
15932 response->proxy_server);
[email protected]029c83b62013-01-24 05:28:2015933
15934 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615935 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015936 TestLoadTimingNotReusedWithPac(load_timing_info,
15937 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015938}
15939
rsleevidb16bb02015-11-12 23:47:1715940// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15941// literal host.
bncd16676a2016-07-20 16:23:0115942TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915943 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615944 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4915945 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1415946 RecordingBoundTestNetLog log;
rsleevidb16bb02015-11-12 23:47:1715947 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915948 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715949
15950 HttpRequestInfo request;
15951 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515952 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1015953 request.traffic_annotation =
15954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715955
15956 // Since we have proxy, should try to establish tunnel.
15957 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515958 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15959 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715960 "Proxy-Connection: keep-alive\r\n\r\n"),
15961
15962 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515963 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715964 "Connection: keep-alive\r\n\r\n"),
15965 };
15966
15967 MockRead data_reads1[] = {
15968 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15969
15970 MockRead("HTTP/1.1 200 OK\r\n"),
15971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15972 MockRead("Content-Length: 100\r\n\r\n"),
15973 MockRead(SYNCHRONOUS, OK),
15974 };
15975
Ryan Sleevib8d7ea02018-05-07 20:01:0115976 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715977 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15978 SSLSocketDataProvider ssl(ASYNC, OK);
15979 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15980
15981 TestCompletionCallback callback1;
15982
bnc691fda62016-08-12 00:43:1615983 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715984
bnc691fda62016-08-12 00:43:1615985 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115986 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715987
15988 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115989 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415990 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715991 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015992 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15993 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715994 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015995 entries, pos,
15996 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15997 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715998
bnc691fda62016-08-12 00:43:1615999 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216000 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1716001
16002 EXPECT_TRUE(response->headers->IsKeepAlive());
16003 EXPECT_EQ(200, response->headers->response_code());
16004 EXPECT_EQ(100, response->headers->GetContentLength());
16005 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16006 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716007 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16008 HostPortPair::FromString("myproxy:70")),
16009 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1716010
16011 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616012 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1716013 TestLoadTimingNotReusedWithPac(load_timing_info,
16014 CONNECT_TIMING_HAS_SSL_TIMES);
16015}
16016
[email protected]76a505b2010-08-25 06:23:0016017// Test a basic HTTPS GET request through a proxy, but the server hangs up
16018// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0116019TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616020 session_deps_.proxy_resolution_service =
16021 ConfiguredProxyResolutionService::CreateFixed(
16022 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416023 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716024 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916025 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016026
[email protected]76a505b2010-08-25 06:23:0016027 HttpRequestInfo request;
16028 request.method = "GET";
bncce36dca22015-04-21 22:11:2316029 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016030 request.traffic_annotation =
16031 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016032
16033 // Since we have proxy, should try to establish tunnel.
16034 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716035 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16036 "Host: www.example.org:443\r\n"
16037 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016038
rsleevidb16bb02015-11-12 23:47:1716039 MockWrite("GET / HTTP/1.1\r\n"
16040 "Host: www.example.org\r\n"
16041 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016042 };
16043
16044 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0016045 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616046 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0016047 };
16048
Ryan Sleevib8d7ea02018-05-07 20:01:0116049 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716050 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616051 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016053
[email protected]49639fa2011-12-20 23:22:4116054 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016055
bnc691fda62016-08-12 00:43:1616056 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5016057
bnc691fda62016-08-12 00:43:1616058 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016060
16061 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116062 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5416063 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016064 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016065 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16066 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016067 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016068 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016069 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16070 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016071}
16072
[email protected]749eefa82010-09-13 22:14:0316073// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0116074TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1316075 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4916076 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116077 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0316078
Raul Tambre94493c652019-03-11 17:18:3516079 spdy::SpdySerializedFrame resp(
16080 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316081 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0316082 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116083 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0316084 };
16085
Ryan Sleevib8d7ea02018-05-07 20:01:0116086 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716087 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0316088
[email protected]8ddf8322012-02-23 18:08:0616089 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616090 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0316092
danakj1fd259a02016-04-16 03:17:0916093 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0316094
16095 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2316096 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4016097 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1116098 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3416099 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16100 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716101 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216102 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316103
16104 HttpRequestInfo request;
16105 request.method = "GET";
bncce36dca22015-04-21 22:11:2316106 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016107 request.traffic_annotation =
16108 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316109
bnc691fda62016-08-12 00:43:1616110 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316111
[email protected]41d64e82013-07-03 22:44:2616112 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016113 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116114 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16115 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316116}
16117
[email protected]73b8dd222010-11-11 19:55:2416118// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616119// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216120void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716121 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916122 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716123 request_info.url = GURL("https://www.example.com/");
16124 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916125 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016126 request_info.traffic_annotation =
16127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716128
[email protected]8ddf8322012-02-23 18:08:0616129 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916130 MockWrite data_writes[] = {
16131 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416132 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116133 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716134 session_deps_.socket_factory->AddSocketDataProvider(&data);
16135 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416136
danakj1fd259a02016-04-16 03:17:0916137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616138 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416139
[email protected]49639fa2011-12-20 23:22:4116140 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016141 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916142 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416143 rv = callback.WaitForResult();
16144 ASSERT_EQ(error, rv);
16145}
16146
bncd16676a2016-07-20 16:23:0116147TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416148 // Just check a grab bag of cert errors.
16149 static const int kErrors[] = {
16150 ERR_CERT_COMMON_NAME_INVALID,
16151 ERR_CERT_AUTHORITY_INVALID,
16152 ERR_CERT_DATE_INVALID,
16153 };
Avi Drissman4365a4782018-12-28 19:26:2416154 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616155 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16156 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416157 }
16158}
16159
[email protected]bd0b6772011-01-11 19:59:3016160// Ensure that a client certificate is removed from the SSL client auth
16161// cache when:
16162// 1) No proxy is involved.
16163// 2) TLS False Start is disabled.
16164// 3) The initial TLS handshake requests a client certificate.
16165// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116166TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916167 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716168 request_info.url = GURL("https://www.example.com/");
16169 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916170 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016171 request_info.traffic_annotation =
16172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716173
David Benjamin1c4b6d012019-07-08 17:12:5716174 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116175 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016176
16177 // [ssl_]data1 contains the data for the first SSL handshake. When a
16178 // CertificateRequest is received for the first time, the handshake will
16179 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916180 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016181 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716182 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116183 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716184 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016185
16186 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16187 // False Start is not being used, the result of the SSL handshake will be
16188 // returned as part of the SSLClientSocket::Connect() call. This test
16189 // matches the result of a server sending a handshake_failure alert,
16190 // rather than a Finished message, because it requires a client
16191 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916192 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016193 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116195 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716196 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016197
16198 // [ssl_]data3 contains the data for the third SSL handshake. When a
16199 // connection to a server fails during an SSL handshake,
David Benjamin07a07d652020-02-26 22:26:5916200 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
16201 // enabled on some errors. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016202 // of the HttpNetworkTransaction. Because this test failure is due to
16203 // requiring a client certificate, this fallback handshake should also
16204 // fail.
ttuttle859dc7a2015-04-23 19:42:2916205 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
David Benjamin07a07d652020-02-26 22:26:5916206 ssl_data3.expected_disable_legacy_crypto = false;
[email protected]bd0b6772011-01-11 19:59:3016207 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116209 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716210 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016211
danakj1fd259a02016-04-16 03:17:0916212 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616213 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016214
[email protected]bd0b6772011-01-11 19:59:3016215 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116216 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016217 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116218 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016219
16220 // Complete the SSL handshake, which should abort due to requiring a
16221 // client certificate.
16222 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116223 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016224
16225 // Indicate that no certificate should be supplied. From the perspective
16226 // of SSLClientCertCache, NULL is just as meaningful as a real
16227 // certificate, so this is the same as supply a
16228 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516229 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116230 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016231
16232 // Ensure the certificate was added to the client auth cache before
16233 // allowing the connection to continue restarting.
16234 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416235 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116236 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416237 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216238 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016239
16240 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716241 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16242 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016243 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116244 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016245
16246 // Ensure that the client certificate is removed from the cache on a
16247 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116248 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416249 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016250}
16251
16252// Ensure that a client certificate is removed from the SSL client auth
16253// cache when:
16254// 1) No proxy is involved.
16255// 2) TLS False Start is enabled.
16256// 3) The initial TLS handshake requests a client certificate.
16257// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116258TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916259 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716260 request_info.url = GURL("https://www.example.com/");
16261 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916262 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016263 request_info.traffic_annotation =
16264 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716265
David Benjamin1c4b6d012019-07-08 17:12:5716266 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116267 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016268
16269 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16270 // return successfully after reading up to the peer's Certificate message.
16271 // This is to allow the caller to call SSLClientSocket::Write(), which can
16272 // enqueue application data to be sent in the same packet as the
16273 // ChangeCipherSpec and Finished messages.
16274 // The actual handshake will be finished when SSLClientSocket::Read() is
16275 // called, which expects to process the peer's ChangeCipherSpec and
16276 // Finished messages. If there was an error negotiating with the peer,
16277 // such as due to the peer requiring a client certificate when none was
16278 // supplied, the alert sent by the peer won't be processed until Read() is
16279 // called.
16280
16281 // Like the non-False Start case, when a client certificate is requested by
16282 // the peer, the handshake is aborted during the Connect() call.
16283 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916284 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016285 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716286 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116287 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716288 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016289
16290 // When a client certificate is supplied, Connect() will not be aborted
16291 // when the peer requests the certificate. Instead, the handshake will
16292 // artificially succeed, allowing the caller to write the HTTP request to
16293 // the socket. The handshake messages are not processed until Read() is
16294 // called, which then detects that the handshake was aborted, due to the
16295 // peer sending a handshake_failure because it requires a client
16296 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916297 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016298 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716299 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916300 MockRead data2_reads[] = {
16301 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016302 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116303 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716304 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016305
16306 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716307 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16308 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916309 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016310 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116312 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716313 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016314
[email protected]80c75f682012-05-26 16:22:1716315 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16316 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916317 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716318 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116320 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716321 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716322
[email protected]7799de12013-05-30 05:52:5116323 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916324 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116325 ssl_data5.cert_request_info = cert_request.get();
16326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116327 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116328 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16329
danakj1fd259a02016-04-16 03:17:0916330 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616331 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016332
[email protected]bd0b6772011-01-11 19:59:3016333 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116334 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016335 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116336 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016337
16338 // Complete the SSL handshake, which should abort due to requiring a
16339 // client certificate.
16340 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116341 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016342
16343 // Indicate that no certificate should be supplied. From the perspective
16344 // of SSLClientCertCache, NULL is just as meaningful as a real
16345 // certificate, so this is the same as supply a
16346 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516347 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116348 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016349
16350 // Ensure the certificate was added to the client auth cache before
16351 // allowing the connection to continue restarting.
16352 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416353 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116354 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416355 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216356 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016357
[email protected]bd0b6772011-01-11 19:59:3016358 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716359 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16360 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016361 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116362 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016363
16364 // Ensure that the client certificate is removed from the cache on a
16365 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116366 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416367 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016368}
16369
[email protected]8c405132011-01-11 22:03:1816370// Ensure that a client certificate is removed from the SSL client auth
16371// cache when:
16372// 1) An HTTPS proxy is involved.
16373// 3) The HTTPS proxy requests a client certificate.
16374// 4) The client supplies an invalid/unacceptable certificate for the
16375// proxy.
bncd16676a2016-07-20 16:23:0116376TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616377 session_deps_.proxy_resolution_service =
16378 ConfiguredProxyResolutionService::CreateFixed(
16379 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416380 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716381 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816382
David Benjamin3b94b0f2019-04-25 23:07:5216383 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116384 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816385
David Benjamin3b94b0f2019-04-25 23:07:5216386 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16387 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916388 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816389 requests[0].url = GURL("https://www.example.com/");
16390 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916391 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016392 requests[0].traffic_annotation =
16393 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816394
David Benjamin3b94b0f2019-04-25 23:07:5216395 // HTTPS requests are tunneled.
16396 MockWrite https_writes[] = {
16397 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16398 "Host: www.example.com:443\r\n"
16399 "Proxy-Connection: keep-alive\r\n\r\n"),
16400 };
16401
[email protected]8c405132011-01-11 22:03:1816402 requests[1].url = GURL("http://www.example.com/");
16403 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916404 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1016405 requests[1].traffic_annotation =
16406 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816407
David Benjamin3b94b0f2019-04-25 23:07:5216408 // HTTP requests are not.
16409 MockWrite http_writes[] = {
16410 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16411 "Host: www.example.com\r\n"
16412 "Proxy-Connection: keep-alive\r\n\r\n"),
16413 };
[email protected]8c405132011-01-11 22:03:1816414
David Benjamin3b94b0f2019-04-25 23:07:5216415 // When the server rejects the client certificate, it will close the
16416 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16417 // TLS 1.2 with False Start), the error is returned out of the first Read().
16418 for (bool reject_in_connect : {true, false}) {
16419 SCOPED_TRACE(reject_in_connect);
16420 // Client certificate errors are typically signaled with
16421 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16422 // protocol error.
16423 for (Error reject_error :
16424 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16425 SCOPED_TRACE(reject_error);
16426 // Tunneled and non-tunneled requests are handled differently. Test both.
16427 for (const HttpRequestInfo& request : requests) {
16428 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816429
David Benjamin3b94b0f2019-04-25 23:07:5216430 session_deps_.socket_factory =
16431 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816432
David Benjamin3b94b0f2019-04-25 23:07:5216433 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
David Benjamin07a07d652020-02-26 22:26:5916434 // [ssl_]data[1-3].
David Benjamin3b94b0f2019-04-25 23:07:5216435 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16436 ssl_data1.cert_request_info = cert_request.get();
16437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16438 StaticSocketDataProvider data1;
16439 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816440
David Benjamin3b94b0f2019-04-25 23:07:5216441 base::Optional<SSLSocketDataProvider> ssl_data2;
16442 base::Optional<StaticSocketDataProvider> data2;
16443 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16444 if (reject_in_connect) {
16445 ssl_data2.emplace(ASYNC, reject_error);
16446 // There are no reads or writes.
16447 data2.emplace();
16448 } else {
16449 ssl_data2.emplace(ASYNC, OK);
16450 // We will get one Write() in before observing the error in Read().
16451 if (request.url.SchemeIsCryptographic()) {
16452 data2.emplace(error_in_read, https_writes);
16453 } else {
16454 data2.emplace(error_in_read, http_writes);
16455 }
16456 }
16457 ssl_data2->cert_request_info = cert_request.get();
David Benjamin3b94b0f2019-04-25 23:07:5216458 session_deps_.socket_factory->AddSSLSocketDataProvider(
16459 &ssl_data2.value());
16460 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816461
David Benjamin07a07d652020-02-26 22:26:5916462 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
16463 // connect twice.
16464 base::Optional<SSLSocketDataProvider> ssl_data3;
16465 base::Optional<StaticSocketDataProvider> data3;
16466 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
16467 ssl_data3.emplace(ASYNC, reject_error);
16468 data3.emplace(); // There are no reads or writes.
16469 ssl_data3->cert_request_info = cert_request.get();
16470 session_deps_.socket_factory->AddSSLSocketDataProvider(
16471 &ssl_data3.value());
16472 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
16473 }
16474
David Benjamin3b94b0f2019-04-25 23:07:5216475 std::unique_ptr<HttpNetworkSession> session =
16476 CreateSession(&session_deps_);
16477 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16478
16479 // Begin the SSL handshake with the proxy.
16480 TestCompletionCallback callback;
16481 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16482 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16483
16484 // Complete the SSL handshake, which should abort due to requiring a
16485 // client certificate.
16486 rv = callback.WaitForResult();
16487 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16488
16489 // Indicate that no certificate should be supplied. From the
16490 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16491 // real certificate, so this is the same as supply a
16492 // legitimate-but-unacceptable certificate.
16493 rv =
16494 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16495 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16496
16497 // Ensure the certificate was added to the client auth cache before
16498 // allowing the connection to continue restarting.
16499 scoped_refptr<X509Certificate> client_cert;
16500 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116501 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216502 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16503 ASSERT_FALSE(client_cert);
16504 // Ensure the certificate was NOT cached for the endpoint. This only
16505 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116506 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216507 HostPortPair("www.example.com", 443), &client_cert,
16508 &client_private_key));
16509
16510 // Restart the handshake. This will consume ssl_data2. The result code
16511 // is checked against what ssl_data2 should return.
16512 rv = callback.WaitForResult();
16513 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16514 IsError(reject_error)));
16515
16516 // Now that the new handshake has failed, ensure that the client
16517 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116518 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216519 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116520 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216521 HostPortPair("www.example.com", 443), &client_cert,
16522 &client_private_key));
16523 }
16524 }
[email protected]8c405132011-01-11 22:03:1816525 }
16526}
16527
David Benjamin1a0566082019-04-30 07:36:1916528// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16529// requests during a TLS renegotiation.
16530TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16531 HttpRequestInfo request_info;
16532 request_info.url = GURL("https://www.example.com/");
16533 request_info.method = "GET";
16534 request_info.load_flags = LOAD_NORMAL;
16535 request_info.traffic_annotation =
16536 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16537
16538 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16539 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16540
16541 std::unique_ptr<FakeClientCertIdentity> identity =
16542 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16543 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16544 ASSERT_TRUE(identity);
16545
16546 // The first connection's handshake succeeds, but we get
16547 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16548 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16549 ssl_data1.cert_request_info = cert_request.get();
16550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16551 MockWrite data1_writes[] = {
16552 MockWrite("GET / HTTP/1.1\r\n"
16553 "Host: www.example.com\r\n"
16554 "Connection: keep-alive\r\n\r\n"),
16555 };
16556 MockRead data1_reads[] = {
16557 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16558 };
16559 StaticSocketDataProvider data1(data1_reads, data1_writes);
16560 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16561
16562 // After supplying with certificate, we restart the request from the top,
16563 // which succeeds this time.
16564 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16565 ssl_data2.expected_send_client_cert = true;
16566 ssl_data2.expected_client_cert = identity->certificate();
16567 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16568 MockWrite data2_writes[] = {
16569 MockWrite("GET / HTTP/1.1\r\n"
16570 "Host: www.example.com\r\n"
16571 "Connection: keep-alive\r\n\r\n"),
16572 };
16573 MockRead data2_reads[] = {
16574 MockRead("HTTP/1.1 200 OK\r\n"
16575 "Content-Length: 0\r\n\r\n"),
16576 };
16577 StaticSocketDataProvider data2(data2_reads, data2_writes);
16578 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16579
16580 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16581 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16582
16583 TestCompletionCallback callback;
16584 int rv = callback.GetResult(
16585 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16586 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16587
16588 rv = trans.RestartWithCertificate(identity->certificate(),
16589 identity->ssl_private_key(),
16590 callback.callback());
16591 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16592
16593 // Ensure the certificate was added to the client auth cache
16594 // allowing the connection to continue restarting.
16595 scoped_refptr<X509Certificate> client_cert;
16596 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116597 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916598 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16599 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16600
16601 // Complete the handshake. The request now succeeds.
16602 rv = callback.WaitForResult();
16603 ASSERT_THAT(rv, IsError(OK));
16604 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16605
16606 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116607 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916608 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16609 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16610}
16611
bncd16676a2016-07-20 16:23:0116612TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616613 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916614 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916615 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616616
bnc032658ba2016-09-26 18:17:1516617 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616618
Ryan Hamilton0239aac2018-05-19 00:03:1316619 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916620 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816621 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316622 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716623 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616624 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116625 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616626 };
Ryan Hamilton0239aac2018-05-19 00:03:1316627 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516628 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316629 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116630 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316631 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516632 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316633 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116634 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616635 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116636 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16637 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316638 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616639 };
16640
eroman36d84e54432016-03-17 03:23:0216641 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216642 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116643 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716644 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616645
[email protected]aa22b242011-11-16 18:58:2916646 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616647 HttpRequestInfo request1;
16648 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316649 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616650 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016651 request1.traffic_annotation =
16652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016653 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616654
tfarina42834112016-09-22 13:38:2016655 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116656 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16657 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616658
16659 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216660 ASSERT_TRUE(response);
16661 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216662 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616663
16664 std::string response_data;
robpercival214763f2016-07-01 23:27:0116665 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616666 EXPECT_EQ("hello!", response_data);
16667
bnca4d611d2016-09-22 19:55:3716668 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316669 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316670 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16671 base::nullopt);
robpercival214763f2016-07-01 23:27:0116672 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616673
16674 HttpRequestInfo request2;
16675 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716676 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616677 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016678 request2.traffic_annotation =
16679 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016680 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616681
tfarina42834112016-09-22 13:38:2016682 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116683 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16684 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616685
16686 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216687 ASSERT_TRUE(response);
16688 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216689 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616690 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216691 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116692 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616693 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616694}
16695
bncd16676a2016-07-20 16:23:0116696TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0216697 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916698 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0216700
bnc032658ba2016-09-26 18:17:1516701 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0216702
Ryan Hamilton0239aac2018-05-19 00:03:1316703 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916704 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816705 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316706 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716707 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0216708 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116709 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0216710 };
Ryan Hamilton0239aac2018-05-19 00:03:1316711 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516712 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316713 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116714 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316715 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516716 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316717 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116718 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0216719 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116720 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16721 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316722 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0216723 };
16724
eroman36d84e54432016-03-17 03:23:0216725 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216726 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116727 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716728 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0216729
16730 TestCompletionCallback callback;
16731 HttpRequestInfo request1;
16732 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316733 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0216734 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016735 request1.traffic_annotation =
16736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016737 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216738
tfarina42834112016-09-22 13:38:2016739 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116740 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16741 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216742
16743 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216744 ASSERT_TRUE(response);
16745 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216746 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216747
16748 std::string response_data;
robpercival214763f2016-07-01 23:27:0116749 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216750 EXPECT_EQ("hello!", response_data);
16751
16752 HttpRequestInfo request2;
16753 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716754 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0216755 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016756 request2.traffic_annotation =
16757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016758 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216759
tfarina42834112016-09-22 13:38:2016760 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116761 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16762 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216763
16764 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216765 ASSERT_TRUE(response);
16766 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216767 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216768 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216769 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116770 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216771 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0216772}
16773
bnc8016c1f2017-03-31 02:11:2916774// Regression test for https://crbug.com/546991.
16775// The server might not be able to serve an IP pooled request, and might send a
16776// 421 Misdirected Request response status to indicate this.
16777// HttpNetworkTransaction should reset the request and retry without IP pooling.
16778TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
16779 // Two hosts resolve to the same IP address.
16780 const std::string ip_addr = "1.2.3.4";
16781 IPAddress ip;
16782 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16783 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16784
Jeremy Roman0579ed62017-08-29 15:56:1916785 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916786 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16787 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16788
16789 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16790
16791 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316792 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916793 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16794 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316795 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916796 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316797 spdy::SpdySerializedFrame rst(
16798 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916799 MockWrite writes1[] = {
16800 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16801 CreateMockWrite(rst, 6),
16802 };
16803
16804 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316805 spdy::SpdySerializedFrame resp1(
16806 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16807 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16808 spdy::SpdyHeaderBlock response_headers;
16809 response_headers[spdy::kHttp2StatusHeader] = "421";
16810 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916811 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16812 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16813 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16814
16815 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116816 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916817 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16818
16819 AddSSLSocketData();
16820
16821 // Retry the second request on a second connection.
16822 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316823 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916824 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16825 MockWrite writes2[] = {
16826 CreateMockWrite(req3, 0),
16827 };
16828
Ryan Hamilton0239aac2018-05-19 00:03:1316829 spdy::SpdySerializedFrame resp3(
16830 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16831 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916832 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16833 MockRead(ASYNC, 0, 3)};
16834
16835 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116836 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916837 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16838
16839 AddSSLSocketData();
16840
16841 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316842 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316843 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16844 base::nullopt);
bnc8016c1f2017-03-31 02:11:2916845 EXPECT_THAT(rv, IsOk());
16846
16847 HttpRequestInfo request1;
16848 request1.method = "GET";
16849 request1.url = GURL("https://www.example.org/");
16850 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016851 request1.traffic_annotation =
16852 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916853 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16854
Eric Orthf4db66a2019-02-19 21:35:3316855 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916856 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16858 rv = callback.WaitForResult();
16859 EXPECT_THAT(rv, IsOk());
16860
16861 const HttpResponseInfo* response = trans1.GetResponseInfo();
16862 ASSERT_TRUE(response);
16863 ASSERT_TRUE(response->headers);
16864 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16865 EXPECT_TRUE(response->was_fetched_via_spdy);
16866 EXPECT_TRUE(response->was_alpn_negotiated);
16867 std::string response_data;
16868 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16869 EXPECT_EQ("hello!", response_data);
16870
16871 HttpRequestInfo request2;
16872 request2.method = "GET";
16873 request2.url = GURL("https://mail.example.org/");
16874 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016875 request2.traffic_annotation =
16876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916877 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16878
Matt Muellerd9342e3a2019-11-26 01:41:1416879 RecordingBoundTestNetLog log;
bnc8016c1f2017-03-31 02:11:2916880 rv = trans2.Start(&request2, callback.callback(), log.bound());
16881 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16882 rv = callback.WaitForResult();
16883 EXPECT_THAT(rv, IsOk());
16884
16885 response = trans2.GetResponseInfo();
16886 ASSERT_TRUE(response);
16887 ASSERT_TRUE(response->headers);
16888 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16889 EXPECT_TRUE(response->was_fetched_via_spdy);
16890 EXPECT_TRUE(response->was_alpn_negotiated);
16891 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16892 EXPECT_EQ("hello!", response_data);
16893
Eric Roman79cc7552019-07-19 02:17:5416894 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916895 ExpectLogContainsSomewhere(
16896 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916897 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916898}
16899
16900// Test that HTTP 421 responses are properly returned to the caller if received
16901// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16902// portions of the response.
16903TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16904 // Two hosts resolve to the same IP address.
16905 const std::string ip_addr = "1.2.3.4";
16906 IPAddress ip;
16907 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16908 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16909
Jeremy Roman0579ed62017-08-29 15:56:1916910 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916911 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16912 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16913
16914 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16915
16916 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316917 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916918 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16919 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316920 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916921 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316922 spdy::SpdySerializedFrame rst(
16923 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916924 MockWrite writes1[] = {
16925 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16926 CreateMockWrite(rst, 6),
16927 };
16928
16929 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316930 spdy::SpdySerializedFrame resp1(
16931 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16932 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16933 spdy::SpdyHeaderBlock response_headers;
16934 response_headers[spdy::kHttp2StatusHeader] = "421";
16935 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916936 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16937 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16938 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16939
16940 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116941 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916942 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16943
16944 AddSSLSocketData();
16945
16946 // Retry the second request on a second connection. It returns 421 Misdirected
16947 // Retry again.
16948 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316949 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916950 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16951 MockWrite writes2[] = {
16952 CreateMockWrite(req3, 0),
16953 };
16954
Ryan Hamilton0239aac2018-05-19 00:03:1316955 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916956 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316957 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916958 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16959 MockRead(ASYNC, 0, 3)};
16960
16961 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116962 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916963 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16964
16965 AddSSLSocketData();
16966
16967 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316968 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316969 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16970 base::nullopt);
davidbence688ae2017-05-04 15:12:5916971 EXPECT_THAT(rv, IsOk());
16972
16973 HttpRequestInfo request1;
16974 request1.method = "GET";
16975 request1.url = GURL("https://www.example.org/");
16976 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016977 request1.traffic_annotation =
16978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916979 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16980
Eric Orthf4db66a2019-02-19 21:35:3316981 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916982 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16984 rv = callback.WaitForResult();
16985 EXPECT_THAT(rv, IsOk());
16986
16987 const HttpResponseInfo* response = trans1.GetResponseInfo();
16988 ASSERT_TRUE(response);
16989 ASSERT_TRUE(response->headers);
16990 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16991 EXPECT_TRUE(response->was_fetched_via_spdy);
16992 EXPECT_TRUE(response->was_alpn_negotiated);
16993 std::string response_data;
16994 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16995 EXPECT_EQ("hello!", response_data);
16996
16997 HttpRequestInfo request2;
16998 request2.method = "GET";
16999 request2.url = GURL("https://mail.example.org/");
17000 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017001 request2.traffic_annotation =
17002 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917003 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17004
Matt Muellerd9342e3a2019-11-26 01:41:1417005 RecordingBoundTestNetLog log;
davidbence688ae2017-05-04 15:12:5917006 rv = trans2.Start(&request2, callback.callback(), log.bound());
17007 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17008 rv = callback.WaitForResult();
17009 EXPECT_THAT(rv, IsOk());
17010
17011 // After a retry, the 421 Misdirected Request is reported back up to the
17012 // caller.
17013 response = trans2.GetResponseInfo();
17014 ASSERT_TRUE(response);
17015 ASSERT_TRUE(response->headers);
17016 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
17017 EXPECT_TRUE(response->was_fetched_via_spdy);
17018 EXPECT_TRUE(response->was_alpn_negotiated);
17019 EXPECT_TRUE(response->ssl_info.cert);
17020 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17021 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2917022}
17023
bncd16676a2016-07-20 16:23:0117024TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1317025 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3417026 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
17027 session_deps_.host_resolver =
17028 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0917029 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617030
bnc032658ba2016-09-26 18:17:1517031 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617032
Ryan Hamilton0239aac2018-05-19 00:03:1317033 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917034 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817035 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317036 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717037 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617038 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117039 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617040 };
Ryan Hamilton0239aac2018-05-19 00:03:1317041 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517042 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317043 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117044 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317045 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517046 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317047 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117048 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617049 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117050 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17051 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317052 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617053 };
17054
eroman36d84e54432016-03-17 03:23:0217055 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217056 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117057 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717058 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617059
[email protected]aa22b242011-11-16 18:58:2917060 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617061 HttpRequestInfo request1;
17062 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317063 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617064 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017065 request1.traffic_annotation =
17066 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017067 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617068
tfarina42834112016-09-22 13:38:2017069 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117070 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17071 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617072
17073 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217074 ASSERT_TRUE(response);
17075 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217076 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617077
17078 std::string response_data;
robpercival214763f2016-07-01 23:27:0117079 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617080 EXPECT_EQ("hello!", response_data);
17081
17082 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317083 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317084 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17085 base::nullopt);
robpercival214763f2016-07-01 23:27:0117086 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617087
17088 HttpRequestInfo request2;
17089 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717090 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617091 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017092 request2.traffic_annotation =
17093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017094 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617095
tfarina42834112016-09-22 13:38:2017096 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117097 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17098 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617099
17100 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217101 ASSERT_TRUE(response);
17102 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217103 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617104 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217105 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117106 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617107 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617108}
17109
bncd16676a2016-07-20 16:23:0117110TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317111 const std::string https_url = "https://www.example.org:8080/";
17112 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417113
17114 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317115 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917116 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417117
17118 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117119 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417120 };
17121
Raul Tambre94493c652019-03-11 17:18:3517122 spdy::SpdySerializedFrame resp1(
17123 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317124 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117125 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917126 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417127
Ryan Sleevib8d7ea02018-05-07 20:01:0117128 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417129 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717130 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417131
17132 // HTTP GET for the HTTP URL
17133 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317134 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417135 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317136 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417137 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417138 };
17139
17140 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317141 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17142 MockRead(ASYNC, 2, "hello"),
17143 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417144 };
17145
Ryan Sleevib8d7ea02018-05-07 20:01:0117146 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417147
[email protected]8450d722012-07-02 19:14:0417148 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617149 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717150 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17151 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17152 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417153
danakj1fd259a02016-04-16 03:17:0917154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417155
17156 // Start the first transaction to set up the SpdySession
17157 HttpRequestInfo request1;
17158 request1.method = "GET";
17159 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417160 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017161 request1.traffic_annotation =
17162 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017163 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417164 TestCompletionCallback callback1;
17165 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017166 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517167 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417168
robpercival214763f2016-07-01 23:27:0117169 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417170 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17171
17172 // Now, start the HTTP request
17173 HttpRequestInfo request2;
17174 request2.method = "GET";
17175 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417176 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017177 request2.traffic_annotation =
17178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017179 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417180 TestCompletionCallback callback2;
17181 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017182 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517183 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417184
robpercival214763f2016-07-01 23:27:0117185 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417186 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17187}
17188
bnc5452e2a2015-05-08 16:27:4217189// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17190// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117191TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517192 url::SchemeHostPort server("https", "www.example.org", 443);
17193 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217194
bnc8bef8da22016-05-30 01:28:2517195 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217196 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617197 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17199
17200 // No data should be read from the alternative, because HTTP/1.1 is
17201 // negotiated.
17202 StaticSocketDataProvider data;
17203 session_deps_.socket_factory->AddSocketDataProvider(&data);
17204
17205 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617206 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217207 // mocked. This way the request relies on the alternate Job.
17208 StaticSocketDataProvider data_refused;
17209 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17210 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17211
zhongyi3d4a55e72016-04-22 20:36:4617212 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917213 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017214 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217215 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117216 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217217 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117218 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717219 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217220
bnc5452e2a2015-05-08 16:27:4217221 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617222 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217223 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517224 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1017225 request.traffic_annotation =
17226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217227 TestCompletionCallback callback;
17228
17229 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217230 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017231 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217232 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217233}
17234
bnc40448a532015-05-11 19:13:1417235// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617236// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417237// succeeds, the request should succeed, even if the latter fails because
17238// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117239TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517240 url::SchemeHostPort server("https", "www.example.org", 443);
17241 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417242
17243 // Negotiate HTTP/1.1 with alternative.
17244 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617245 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417246 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17247
17248 // No data should be read from the alternative, because HTTP/1.1 is
17249 // negotiated.
17250 StaticSocketDataProvider data;
17251 session_deps_.socket_factory->AddSocketDataProvider(&data);
17252
zhongyi3d4a55e72016-04-22 20:36:4617253 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417254 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617255 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417256 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17257
17258 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517259 MockWrite("GET / HTTP/1.1\r\n"
17260 "Host: www.example.org\r\n"
17261 "Connection: keep-alive\r\n\r\n"),
17262 MockWrite("GET /second HTTP/1.1\r\n"
17263 "Host: www.example.org\r\n"
17264 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417265 };
17266
17267 MockRead http_reads[] = {
17268 MockRead("HTTP/1.1 200 OK\r\n"),
17269 MockRead("Content-Type: text/html\r\n"),
17270 MockRead("Content-Length: 6\r\n\r\n"),
17271 MockRead("foobar"),
17272 MockRead("HTTP/1.1 200 OK\r\n"),
17273 MockRead("Content-Type: text/html\r\n"),
17274 MockRead("Content-Length: 7\r\n\r\n"),
17275 MockRead("another"),
17276 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117277 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417278 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17279
zhongyi3d4a55e72016-04-22 20:36:4617280 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917281 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017282 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417283 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117284 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217285 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117286 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717287 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417288
17289 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17290 HttpRequestInfo request1;
17291 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517292 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417293 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017294 request1.traffic_annotation =
17295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417296 TestCompletionCallback callback1;
17297
tfarina42834112016-09-22 13:38:2017298 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417299 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117300 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417301
17302 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217303 ASSERT_TRUE(response1);
17304 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417305 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17306
17307 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117308 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417309 EXPECT_EQ("foobar", response_data1);
17310
17311 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17312 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517313 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17314 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417315
zhongyi3d4a55e72016-04-22 20:36:4617316 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417317 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617318 // to server.
bnc40448a532015-05-11 19:13:1417319 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17320 HttpRequestInfo request2;
17321 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517322 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417323 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017324 request2.traffic_annotation =
17325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417326 TestCompletionCallback callback2;
17327
tfarina42834112016-09-22 13:38:2017328 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417329 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117330 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417331
17332 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217333 ASSERT_TRUE(response2);
17334 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417335 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17336
17337 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117338 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417339 EXPECT_EQ("another", response_data2);
17340}
17341
bnc5452e2a2015-05-08 16:27:4217342// Alternative service requires HTTP/2 (or SPDY), but there is already a
17343// HTTP/1.1 socket open to the alternative server. That socket should not be
17344// used.
bncd16676a2016-07-20 16:23:0117345TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617346 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217347 HostPortPair alternative("alternative.example.org", 443);
17348 std::string origin_url = "https://origin.example.org:443";
17349 std::string alternative_url = "https://alternative.example.org:443";
17350
17351 // Negotiate HTTP/1.1 with alternative.example.org.
17352 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617353 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217354 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17355
17356 // HTTP/1.1 data for |request1| and |request2|.
17357 MockWrite http_writes[] = {
17358 MockWrite(
17359 "GET / HTTP/1.1\r\n"
17360 "Host: alternative.example.org\r\n"
17361 "Connection: keep-alive\r\n\r\n"),
17362 MockWrite(
17363 "GET / HTTP/1.1\r\n"
17364 "Host: alternative.example.org\r\n"
17365 "Connection: keep-alive\r\n\r\n"),
17366 };
17367
17368 MockRead http_reads[] = {
17369 MockRead(
17370 "HTTP/1.1 200 OK\r\n"
17371 "Content-Type: text/html; charset=iso-8859-1\r\n"
17372 "Content-Length: 40\r\n\r\n"
17373 "first HTTP/1.1 response from alternative"),
17374 MockRead(
17375 "HTTP/1.1 200 OK\r\n"
17376 "Content-Type: text/html; charset=iso-8859-1\r\n"
17377 "Content-Length: 41\r\n\r\n"
17378 "second HTTP/1.1 response from alternative"),
17379 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117380 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217381 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17382
17383 // This test documents that an alternate Job should not pool to an already
17384 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617385 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217386 StaticSocketDataProvider data_refused;
17387 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17388 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17389
zhongyi3d4a55e72016-04-22 20:36:4617390 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917391 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017392 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217393 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117394 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217395 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117396 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717397 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217398
17399 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217400 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617401 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217402 request1.method = "GET";
17403 request1.url = GURL(alternative_url);
17404 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017405 request1.traffic_annotation =
17406 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217407 TestCompletionCallback callback1;
17408
tfarina42834112016-09-22 13:38:2017409 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117410 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617411 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217412 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217413 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217414 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217415 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217416 EXPECT_FALSE(response1->was_fetched_via_spdy);
17417 std::string response_data1;
bnc691fda62016-08-12 00:43:1617418 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217419 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17420
17421 // Request for origin.example.org, which has an alternative service. This
17422 // will start two Jobs: the alternative looks for connections to pool to,
17423 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617424 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217425 // this request fails.
bnc5452e2a2015-05-08 16:27:4217426 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617427 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217428 request2.method = "GET";
17429 request2.url = GURL(origin_url);
17430 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017431 request2.traffic_annotation =
17432 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217433 TestCompletionCallback callback2;
17434
tfarina42834112016-09-22 13:38:2017435 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117436 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217437
17438 // Another transaction to alternative. This is to test that the HTTP/1.1
17439 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217440 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617441 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217442 request3.method = "GET";
17443 request3.url = GURL(alternative_url);
17444 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017445 request3.traffic_annotation =
17446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217447 TestCompletionCallback callback3;
17448
tfarina42834112016-09-22 13:38:2017449 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117450 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617451 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217452 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217453 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217454 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217455 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217456 EXPECT_FALSE(response3->was_fetched_via_spdy);
17457 std::string response_data3;
bnc691fda62016-08-12 00:43:1617458 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217459 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17460}
17461
bncd16676a2016-07-20 16:23:0117462TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317463 const std::string https_url = "https://www.example.org:8080/";
17464 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417465
rdsmithebb50aa2015-11-12 03:44:3817466 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117467 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817468
[email protected]8450d722012-07-02 19:14:0417469 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317470 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417471 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17472 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17473 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317474 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917475 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317476 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217477 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917478
17479 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1317480 spdy::SpdyHeaderBlock req2_block;
17481 req2_block[spdy::kHttp2MethodHeader] = "GET";
17482 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17483 req2_block[spdy::kHttp2SchemeHeader] = "http";
17484 req2_block[spdy::kHttp2PathHeader] = "/";
17485 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517486 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417487
17488 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117489 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17490 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417491 };
17492
Ryan Hamilton0239aac2018-05-19 00:03:1317493 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517494 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317495 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517496 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317497 spdy::SpdySerializedFrame body1(
17498 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17499 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817500 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317501 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817502 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517503 spdy::SpdySerializedFrame resp2(
17504 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317505 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317506 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117507 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317508 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117509 CreateMockRead(wrapped_resp1, 4),
17510 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317511 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117512 CreateMockRead(resp2, 8),
17513 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317514 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17515 };
[email protected]8450d722012-07-02 19:14:0417516
Ryan Sleevib8d7ea02018-05-07 20:01:0117517 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417518 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717519 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417520
Lily Houghton8c2f97d2018-01-22 05:06:5917521 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617522 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4917523 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1417524 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717525 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417526 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617527 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317528 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417529 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617530 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17532 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417533
danakj1fd259a02016-04-16 03:17:0917534 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417535
17536 // Start the first transaction to set up the SpdySession
17537 HttpRequestInfo request1;
17538 request1.method = "GET";
17539 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417540 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017541 request1.traffic_annotation =
17542 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017543 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417544 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017545 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417546
mmenke666a6fea2015-12-19 04:16:3317547 // This pause is a hack to avoid running into https://crbug.com/497228.
17548 data1.RunUntilPaused();
17549 base::RunLoop().RunUntilIdle();
17550 data1.Resume();
robpercival214763f2016-07-01 23:27:0117551 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417552 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17553
[email protected]f6c63db52013-02-02 00:35:2217554 LoadTimingInfo load_timing_info1;
17555 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17556 TestLoadTimingNotReusedWithPac(load_timing_info1,
17557 CONNECT_TIMING_HAS_SSL_TIMES);
17558
mmenke666a6fea2015-12-19 04:16:3317559 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417560 HttpRequestInfo request2;
17561 request2.method = "GET";
17562 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417563 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017564 request2.traffic_annotation =
17565 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017566 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417567 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017568 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417569
mmenke666a6fea2015-12-19 04:16:3317570 // This pause is a hack to avoid running into https://crbug.com/497228.
17571 data1.RunUntilPaused();
17572 base::RunLoop().RunUntilIdle();
17573 data1.Resume();
robpercival214763f2016-07-01 23:27:0117574 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317575
[email protected]8450d722012-07-02 19:14:0417576 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217577
17578 LoadTimingInfo load_timing_info2;
17579 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17580 // The established SPDY sessions is considered reused by the HTTP request.
17581 TestLoadTimingReusedWithPac(load_timing_info2);
17582 // HTTP requests over a SPDY session should have a different connection
17583 // socket_log_id than requests over a tunnel.
17584 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417585}
17586
[email protected]2d88e7d2012-07-19 17:55:1717587// Test that in the case where we have a SPDY session to a SPDY proxy
17588// that we do not pool other origins that resolve to the same IP when
17589// the certificate does not match the new origin.
17590// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117591TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317592 const std::string url1 = "http://www.example.org/";
17593 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717594 const std::string ip_addr = "1.2.3.4";
17595
rdsmithebb50aa2015-11-12 03:44:3817596 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117597 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817598
[email protected]2d88e7d2012-07-19 17:55:1717599 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1317600 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2317601 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317602 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517603 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717604
17605 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117606 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717607 };
17608
Raul Tambre94493c652019-03-11 17:18:3517609 spdy::SpdySerializedFrame resp1(
17610 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317611 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717612 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117613 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17614 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717615 };
17616
Ryan Sleevib8d7ea02018-05-07 20:01:0117617 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217618 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917619 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717620 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17621 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317622 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717623
17624 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317625 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917626 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717627
17628 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117629 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717630 };
17631
Ryan Hamilton0239aac2018-05-19 00:03:1317632 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517633 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317634 spdy::SpdySerializedFrame body2(
17635 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117636 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317637 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717638
Ryan Sleevib8d7ea02018-05-07 20:01:0117639 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717640 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317641 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717642
17643 // Set up a proxy config that sends HTTP requests to a proxy, and
17644 // all others direct.
17645 ProxyConfig proxy_config;
17646 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917647 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617648 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4917649 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17650 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0917651 nullptr, nullptr, /*quick_check_enabled=*/true);
[email protected]2d88e7d2012-07-19 17:55:1717652
bncce36dca22015-04-21 22:11:2317653 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617654 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717655 // Load a valid cert. Note, that this does not need to
17656 // be valid for proxy because the MockSSLClientSocket does
17657 // not actually verify it. But SpdySession will use this
17658 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917659 ssl1.ssl_info.cert =
17660 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17661 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17663 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717664
17665 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617666 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317667 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17668 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717669
Jeremy Roman0579ed62017-08-29 15:56:1917670 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317671 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717672 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717673
danakj1fd259a02016-04-16 03:17:0917674 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717675
17676 // Start the first transaction to set up the SpdySession
17677 HttpRequestInfo request1;
17678 request1.method = "GET";
17679 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1717680 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017681 request1.traffic_annotation =
17682 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017683 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717684 TestCompletionCallback callback1;
17685 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017686 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3317687 // This pause is a hack to avoid running into https://crbug.com/497228.
17688 data1.RunUntilPaused();
17689 base::RunLoop().RunUntilIdle();
17690 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1717691
robpercival214763f2016-07-01 23:27:0117692 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717693 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17694
17695 // Now, start the HTTP request
17696 HttpRequestInfo request2;
17697 request2.method = "GET";
17698 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1717699 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017700 request2.traffic_annotation =
17701 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017702 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717703 TestCompletionCallback callback2;
17704 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017705 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517706 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1717707
17708 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0117709 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717710 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17711}
17712
[email protected]85f97342013-04-17 06:12:2417713// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
17714// error) in SPDY session, removes the socket from pool and closes the SPDY
17715// session. Verify that new url's from the same HttpNetworkSession (and a new
17716// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0117717TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2317718 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2417719
17720 MockRead reads1[] = {
17721 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
17722 };
17723
Ryan Sleevib8d7ea02018-05-07 20:01:0117724 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2417725
Ryan Hamilton0239aac2018-05-19 00:03:1317726 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917727 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2417728 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117729 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2417730 };
17731
Raul Tambre94493c652019-03-11 17:18:3517732 spdy::SpdySerializedFrame resp2(
17733 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317734 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2417735 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4117736 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
17737 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2417738 };
17739
Ryan Sleevib8d7ea02018-05-07 20:01:0117740 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2417741
[email protected]85f97342013-04-17 06:12:2417742 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617743 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17745 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2417746
17747 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617748 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17750 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2417751
danakj1fd259a02016-04-16 03:17:0917752 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5017753 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2417754
17755 // Start the first transaction to set up the SpdySession and verify that
17756 // connection was closed.
17757 HttpRequestInfo request1;
17758 request1.method = "GET";
17759 request1.url = GURL(https_url);
17760 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017761 request1.traffic_annotation =
17762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017763 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417764 TestCompletionCallback callback1;
17765 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017766 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117767 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2417768
17769 // Now, start the second request and make sure it succeeds.
17770 HttpRequestInfo request2;
17771 request2.method = "GET";
17772 request2.url = GURL(https_url);
17773 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017774 request2.traffic_annotation =
17775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017776 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417777 TestCompletionCallback callback2;
17778 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017779 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2417780
robpercival214763f2016-07-01 23:27:0117781 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2417782 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17783}
17784
bncd16676a2016-07-20 16:23:0117785TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317786 ClientSocketPoolManager::set_max_sockets_per_group(
17787 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17788 ClientSocketPoolManager::set_max_sockets_per_pool(
17789 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17790
17791 // Use two different hosts with different IPs so they don't get pooled.
17792 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17793 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317795
17796 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617797 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317798 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617799 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17802
Ryan Hamilton0239aac2018-05-19 00:03:1317803 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917804 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317805 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117806 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317807 };
Ryan Hamilton0239aac2018-05-19 00:03:1317808 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517809 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317810 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117811 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317812 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117813 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917814 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317815 };
17816
rdsmithebb50aa2015-11-12 03:44:3817817 // Use a separate test instance for the separate SpdySession that will be
17818 // created.
bncd16676a2016-07-20 16:23:0117819 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117820 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217821 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317822
Ryan Hamilton0239aac2018-05-19 00:03:1317823 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917824 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317825 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117826 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317827 };
Ryan Hamilton0239aac2018-05-19 00:03:1317828 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517829 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317830 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117831 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317832 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117833 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917834 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317835 };
17836
Ryan Sleevib8d7ea02018-05-07 20:01:0117837 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217838 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317839
17840 MockWrite http_write[] = {
17841 MockWrite("GET / HTTP/1.1\r\n"
17842 "Host: www.a.com\r\n"
17843 "Connection: keep-alive\r\n\r\n"),
17844 };
17845
17846 MockRead http_read[] = {
17847 MockRead("HTTP/1.1 200 OK\r\n"),
17848 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17849 MockRead("Content-Length: 6\r\n\r\n"),
17850 MockRead("hello!"),
17851 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117852 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317853 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17854
17855 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117856 SpdySessionKey spdy_session_key_a(
17857 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417858 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17859 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317860 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617861 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317862
17863 TestCompletionCallback callback;
17864 HttpRequestInfo request1;
17865 request1.method = "GET";
17866 request1.url = GURL("https://www.a.com/");
17867 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017868 request1.traffic_annotation =
17869 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817870 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917871 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317872
tfarina42834112016-09-22 13:38:2017873 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17875 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317876
17877 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217878 ASSERT_TRUE(response);
17879 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217880 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317881 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217882 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317883
17884 std::string response_data;
robpercival214763f2016-07-01 23:27:0117885 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317886 EXPECT_EQ("hello!", response_data);
17887 trans.reset();
17888 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617889 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317890
17891 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117892 SpdySessionKey spdy_session_key_b(
17893 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417894 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17895 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317896 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617897 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317898 HttpRequestInfo request2;
17899 request2.method = "GET";
17900 request2.url = GURL("https://www.b.com/");
17901 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017902 request2.traffic_annotation =
17903 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817904 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917905 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317906
tfarina42834112016-09-22 13:38:2017907 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117908 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17909 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317910
17911 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217912 ASSERT_TRUE(response);
17913 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217914 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317915 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217916 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117917 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317918 EXPECT_EQ("hello!", response_data);
17919 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617920 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317921 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617922 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317923
17924 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117925 SpdySessionKey spdy_session_key_a1(
17926 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417927 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17928 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317929 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617930 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317931 HttpRequestInfo request3;
17932 request3.method = "GET";
17933 request3.url = GURL("http://www.a.com/");
17934 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017935 request3.traffic_annotation =
17936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817937 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917938 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317939
tfarina42834112016-09-22 13:38:2017940 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117941 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17942 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317943
17944 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217945 ASSERT_TRUE(response);
17946 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317947 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17948 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217949 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117950 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317951 EXPECT_EQ("hello!", response_data);
17952 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617953 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317954 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617955 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317956}
17957
bncd16676a2016-07-20 16:23:0117958TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417959 HttpRequestInfo request;
17960 request.method = "GET";
bncce36dca22015-04-21 22:11:2317961 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017962 request.traffic_annotation =
17963 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417964
danakj1fd259a02016-04-16 03:17:0917965 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617966 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417967
ttuttled9dbc652015-09-29 20:00:5917968 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417969 StaticSocketDataProvider data;
17970 data.set_connect_data(mock_connect);
17971 session_deps_.socket_factory->AddSocketDataProvider(&data);
17972
17973 TestCompletionCallback callback;
17974
tfarina42834112016-09-22 13:38:2017975 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117976 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417977
17978 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117979 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417980
ttuttle1f2d7e92015-04-28 16:17:4717981 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617982 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717983 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117984 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917985
17986 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617987 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917988 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417989}
17990
bncd16676a2016-07-20 16:23:0117991TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417992 HttpRequestInfo request;
17993 request.method = "GET";
bncce36dca22015-04-21 22:11:2317994 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017995 request.traffic_annotation =
17996 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417997
danakj1fd259a02016-04-16 03:17:0917998 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617999 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418000
ttuttled9dbc652015-09-29 20:00:5918001 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418002 StaticSocketDataProvider data;
18003 data.set_connect_data(mock_connect);
18004 session_deps_.socket_factory->AddSocketDataProvider(&data);
18005
18006 TestCompletionCallback callback;
18007
tfarina42834112016-09-22 13:38:2018008 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118009 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418010
18011 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118012 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418013
ttuttle1f2d7e92015-04-28 16:17:4718014 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618015 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718016 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118017 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918018
18019 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618020 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918021 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418022}
18023
bncd16676a2016-07-20 16:23:0118024TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418025 HttpRequestInfo request;
18026 request.method = "GET";
bncce36dca22015-04-21 22:11:2318027 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018028 request.traffic_annotation =
18029 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418030
danakj1fd259a02016-04-16 03:17:0918031 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618032 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418033
18034 MockWrite data_writes[] = {
18035 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18036 };
18037 MockRead data_reads[] = {
18038 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18039 };
18040
Ryan Sleevib8d7ea02018-05-07 20:01:0118041 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418042 session_deps_.socket_factory->AddSocketDataProvider(&data);
18043
18044 TestCompletionCallback callback;
18045
tfarina42834112016-09-22 13:38:2018046 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118047 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418048
18049 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118050 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418051}
18052
bncd16676a2016-07-20 16:23:0118053TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418054 HttpRequestInfo request;
18055 request.method = "GET";
bncce36dca22015-04-21 22:11:2318056 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018057 request.traffic_annotation =
18058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418059
danakj1fd259a02016-04-16 03:17:0918060 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618061 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418062
18063 MockWrite data_writes[] = {
18064 MockWrite(ASYNC, ERR_CONNECTION_RESET),
18065 };
18066 MockRead data_reads[] = {
18067 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18068 };
18069
Ryan Sleevib8d7ea02018-05-07 20:01:0118070 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418071 session_deps_.socket_factory->AddSocketDataProvider(&data);
18072
18073 TestCompletionCallback callback;
18074
tfarina42834112016-09-22 13:38:2018075 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118076 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418077
18078 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118079 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418080}
18081
bncd16676a2016-07-20 16:23:0118082TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418083 HttpRequestInfo request;
18084 request.method = "GET";
bncce36dca22015-04-21 22:11:2318085 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018086 request.traffic_annotation =
18087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418088
danakj1fd259a02016-04-16 03:17:0918089 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618090 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418091
18092 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318093 MockWrite(
18094 "GET / HTTP/1.1\r\n"
18095 "Host: www.example.org\r\n"
18096 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418097 };
18098 MockRead data_reads[] = {
18099 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18100 };
18101
Ryan Sleevib8d7ea02018-05-07 20:01:0118102 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418103 session_deps_.socket_factory->AddSocketDataProvider(&data);
18104
18105 TestCompletionCallback callback;
18106
tfarina42834112016-09-22 13:38:2018107 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418109
18110 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118111 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418112}
18113
bncd16676a2016-07-20 16:23:0118114TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418115 HttpRequestInfo request;
18116 request.method = "GET";
bncce36dca22015-04-21 22:11:2318117 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018118 request.traffic_annotation =
18119 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418120
danakj1fd259a02016-04-16 03:17:0918121 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618122 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418123
18124 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318125 MockWrite(
18126 "GET / HTTP/1.1\r\n"
18127 "Host: www.example.org\r\n"
18128 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418129 };
18130 MockRead data_reads[] = {
18131 MockRead(ASYNC, ERR_CONNECTION_RESET),
18132 };
18133
Ryan Sleevib8d7ea02018-05-07 20:01:0118134 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418135 session_deps_.socket_factory->AddSocketDataProvider(&data);
18136
18137 TestCompletionCallback callback;
18138
tfarina42834112016-09-22 13:38:2018139 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118140 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418141
18142 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118143 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418144}
18145
[email protected]043b68c82013-08-22 23:41:5218146// Tests that when a used socket is returned to the SSL socket pool, it's closed
18147// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118148TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218149 ClientSocketPoolManager::set_max_sockets_per_group(
18150 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18151 ClientSocketPoolManager::set_max_sockets_per_pool(
18152 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18153
18154 // Set up SSL request.
18155
18156 HttpRequestInfo ssl_request;
18157 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318158 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018159 ssl_request.traffic_annotation =
18160 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218161
18162 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318163 MockWrite(
18164 "GET / HTTP/1.1\r\n"
18165 "Host: www.example.org\r\n"
18166 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218167 };
18168 MockRead ssl_reads[] = {
18169 MockRead("HTTP/1.1 200 OK\r\n"),
18170 MockRead("Content-Length: 11\r\n\r\n"),
18171 MockRead("hello world"),
18172 MockRead(SYNCHRONOUS, OK),
18173 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118174 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218175 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18176
18177 SSLSocketDataProvider ssl(ASYNC, OK);
18178 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18179
18180 // Set up HTTP request.
18181
18182 HttpRequestInfo http_request;
18183 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318184 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018185 http_request.traffic_annotation =
18186 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218187
18188 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318189 MockWrite(
18190 "GET / HTTP/1.1\r\n"
18191 "Host: www.example.org\r\n"
18192 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218193 };
18194 MockRead http_reads[] = {
18195 MockRead("HTTP/1.1 200 OK\r\n"),
18196 MockRead("Content-Length: 7\r\n\r\n"),
18197 MockRead("falafel"),
18198 MockRead(SYNCHRONOUS, OK),
18199 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118200 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218201 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18202
danakj1fd259a02016-04-16 03:17:0918203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218204
18205 // Start the SSL request.
18206 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618207 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018208 ASSERT_EQ(ERR_IO_PENDING,
18209 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18210 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218211
18212 // Start the HTTP request. Pool should stall.
18213 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618214 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018215 ASSERT_EQ(ERR_IO_PENDING,
18216 http_trans.Start(&http_request, http_callback.callback(),
18217 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118218 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218219
18220 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118221 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218222 std::string response_data;
bnc691fda62016-08-12 00:43:1618223 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218224 EXPECT_EQ("hello world", response_data);
18225
18226 // The SSL socket should automatically be closed, so the HTTP request can
18227 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318228 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118229 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218230
18231 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118232 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618233 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218234 EXPECT_EQ("falafel", response_data);
18235
dcheng48459ac22014-08-26 00:46:4118236 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218237}
18238
18239// Tests that when a SSL connection is established but there's no corresponding
18240// request that needs it, the new socket is closed if the transport socket pool
18241// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118242TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218243 ClientSocketPoolManager::set_max_sockets_per_group(
18244 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18245 ClientSocketPoolManager::set_max_sockets_per_pool(
18246 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18247
18248 // Set up an ssl request.
18249
18250 HttpRequestInfo ssl_request;
18251 ssl_request.method = "GET";
18252 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1018253 ssl_request.traffic_annotation =
18254 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218255
18256 // No data will be sent on the SSL socket.
18257 StaticSocketDataProvider ssl_data;
18258 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18259
18260 SSLSocketDataProvider ssl(ASYNC, OK);
18261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18262
18263 // Set up HTTP request.
18264
18265 HttpRequestInfo http_request;
18266 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318267 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018268 http_request.traffic_annotation =
18269 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218270
18271 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318272 MockWrite(
18273 "GET / HTTP/1.1\r\n"
18274 "Host: www.example.org\r\n"
18275 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218276 };
18277 MockRead http_reads[] = {
18278 MockRead("HTTP/1.1 200 OK\r\n"),
18279 MockRead("Content-Length: 7\r\n\r\n"),
18280 MockRead("falafel"),
18281 MockRead(SYNCHRONOUS, OK),
18282 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118283 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218284 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18285
danakj1fd259a02016-04-16 03:17:0918286 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218287
18288 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18289 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918290 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918291 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318292 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218293
18294 // Start the HTTP request. Pool should stall.
18295 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618296 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018297 ASSERT_EQ(ERR_IO_PENDING,
18298 http_trans.Start(&http_request, http_callback.callback(),
18299 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118300 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218301
18302 // The SSL connection will automatically be closed once the connection is
18303 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118304 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218305 std::string response_data;
bnc691fda62016-08-12 00:43:1618306 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218307 EXPECT_EQ("falafel", response_data);
18308
dcheng48459ac22014-08-26 00:46:4118309 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218310}
18311
bncd16676a2016-07-20 16:23:0118312TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918313 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218314 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918315 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218316 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418317
18318 HttpRequestInfo request;
18319 request.method = "POST";
18320 request.url = GURL("http://www.foo.com/");
18321 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018322 request.traffic_annotation =
18323 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418324
danakj1fd259a02016-04-16 03:17:0918325 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618326 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418327 // Send headers successfully, but get an error while sending the body.
18328 MockWrite data_writes[] = {
18329 MockWrite("POST / HTTP/1.1\r\n"
18330 "Host: www.foo.com\r\n"
18331 "Connection: keep-alive\r\n"
18332 "Content-Length: 3\r\n\r\n"),
18333 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18334 };
18335
18336 MockRead data_reads[] = {
18337 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18338 MockRead("hello world"),
18339 MockRead(SYNCHRONOUS, OK),
18340 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118341 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418342 session_deps_.socket_factory->AddSocketDataProvider(&data);
18343
18344 TestCompletionCallback callback;
18345
tfarina42834112016-09-22 13:38:2018346 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118347 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418348
18349 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118350 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418351
bnc691fda62016-08-12 00:43:1618352 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218353 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418354
wezca1070932016-05-26 20:30:5218355 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418356 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18357
18358 std::string response_data;
bnc691fda62016-08-12 00:43:1618359 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118360 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418361 EXPECT_EQ("hello world", response_data);
18362}
18363
18364// This test makes sure the retry logic doesn't trigger when reading an error
18365// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118366TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418367 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918368 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418369 MockWrite data_writes[] = {
18370 MockWrite("GET / HTTP/1.1\r\n"
18371 "Host: www.foo.com\r\n"
18372 "Connection: keep-alive\r\n\r\n"),
18373 MockWrite("POST / HTTP/1.1\r\n"
18374 "Host: www.foo.com\r\n"
18375 "Connection: keep-alive\r\n"
18376 "Content-Length: 3\r\n\r\n"),
18377 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18378 };
18379
18380 MockRead data_reads[] = {
18381 MockRead("HTTP/1.1 200 Peachy\r\n"
18382 "Content-Length: 14\r\n\r\n"),
18383 MockRead("first response"),
18384 MockRead("HTTP/1.1 400 Not OK\r\n"
18385 "Content-Length: 15\r\n\r\n"),
18386 MockRead("second response"),
18387 MockRead(SYNCHRONOUS, OK),
18388 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118389 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418390 session_deps_.socket_factory->AddSocketDataProvider(&data);
18391
18392 TestCompletionCallback callback;
18393 HttpRequestInfo request1;
18394 request1.method = "GET";
18395 request1.url = GURL("http://www.foo.com/");
18396 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018397 request1.traffic_annotation =
18398 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418399
bnc87dcefc2017-05-25 12:47:5818400 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918401 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018402 int rv = trans1->Start(&request1, 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
18408 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218409 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418410
wezca1070932016-05-26 20:30:5218411 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418412 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18413
18414 std::string response_data1;
18415 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118416 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418417 EXPECT_EQ("first response", response_data1);
18418 // Delete the transaction to release the socket back into the socket pool.
18419 trans1.reset();
18420
danakj1fd259a02016-04-16 03:17:0918421 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218422 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918423 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218424 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418425
18426 HttpRequestInfo request2;
18427 request2.method = "POST";
18428 request2.url = GURL("http://www.foo.com/");
18429 request2.upload_data_stream = &upload_data_stream;
18430 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1018431 request2.traffic_annotation =
18432 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418433
bnc691fda62016-08-12 00:43:1618434 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018435 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118436 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418437
18438 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118439 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418440
bnc691fda62016-08-12 00:43:1618441 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218442 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418443
wezca1070932016-05-26 20:30:5218444 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418445 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18446
18447 std::string response_data2;
bnc691fda62016-08-12 00:43:1618448 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118449 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418450 EXPECT_EQ("second response", response_data2);
18451}
18452
bncd16676a2016-07-20 16:23:0118453TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418454 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918455 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218456 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918457 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218458 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418459
18460 HttpRequestInfo request;
18461 request.method = "POST";
18462 request.url = GURL("http://www.foo.com/");
18463 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018464 request.traffic_annotation =
18465 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418466
danakj1fd259a02016-04-16 03:17:0918467 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618468 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418469 // Send headers successfully, but get an error while sending the body.
18470 MockWrite data_writes[] = {
18471 MockWrite("POST / HTTP/1.1\r\n"
18472 "Host: www.foo.com\r\n"
18473 "Connection: keep-alive\r\n"
18474 "Content-Length: 3\r\n\r\n"
18475 "fo"),
18476 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18477 };
18478
18479 MockRead data_reads[] = {
18480 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18481 MockRead("hello world"),
18482 MockRead(SYNCHRONOUS, OK),
18483 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118484 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418485 session_deps_.socket_factory->AddSocketDataProvider(&data);
18486
18487 TestCompletionCallback callback;
18488
tfarina42834112016-09-22 13:38:2018489 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118490 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418491
18492 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118493 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418494
bnc691fda62016-08-12 00:43:1618495 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218496 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418497
wezca1070932016-05-26 20:30:5218498 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418499 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18500
18501 std::string response_data;
bnc691fda62016-08-12 00:43:1618502 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118503 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418504 EXPECT_EQ("hello world", response_data);
18505}
18506
18507// This tests the more common case than the previous test, where headers and
18508// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118509TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718510 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418511
18512 HttpRequestInfo request;
18513 request.method = "POST";
18514 request.url = GURL("http://www.foo.com/");
18515 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018516 request.traffic_annotation =
18517 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418518
danakj1fd259a02016-04-16 03:17:0918519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618520 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418521 // Send headers successfully, but get an error while sending the body.
18522 MockWrite data_writes[] = {
18523 MockWrite("POST / HTTP/1.1\r\n"
18524 "Host: www.foo.com\r\n"
18525 "Connection: keep-alive\r\n"
18526 "Transfer-Encoding: chunked\r\n\r\n"),
18527 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18528 };
18529
18530 MockRead data_reads[] = {
18531 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18532 MockRead("hello world"),
18533 MockRead(SYNCHRONOUS, OK),
18534 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118535 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418536 session_deps_.socket_factory->AddSocketDataProvider(&data);
18537
18538 TestCompletionCallback callback;
18539
tfarina42834112016-09-22 13:38:2018540 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118541 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418542 // Make sure the headers are sent before adding a chunk. This ensures that
18543 // they can't be merged with the body in a single send. Not currently
18544 // necessary since a chunked body is never merged with headers, but this makes
18545 // the test more future proof.
18546 base::RunLoop().RunUntilIdle();
18547
mmenkecbc2b712014-10-09 20:29:0718548 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418549
18550 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118551 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418552
bnc691fda62016-08-12 00:43:1618553 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218554 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418555
wezca1070932016-05-26 20:30:5218556 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418557 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18558
18559 std::string response_data;
bnc691fda62016-08-12 00:43:1618560 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118561 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418562 EXPECT_EQ("hello world", response_data);
18563}
18564
bncd16676a2016-07-20 16:23:0118565TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918566 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218567 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918568 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218569 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418570
18571 HttpRequestInfo request;
18572 request.method = "POST";
18573 request.url = GURL("http://www.foo.com/");
18574 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018575 request.traffic_annotation =
18576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418577
danakj1fd259a02016-04-16 03:17:0918578 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618579 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418580
18581 MockWrite data_writes[] = {
18582 MockWrite("POST / HTTP/1.1\r\n"
18583 "Host: www.foo.com\r\n"
18584 "Connection: keep-alive\r\n"
18585 "Content-Length: 3\r\n\r\n"),
18586 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18587 };
18588
18589 MockRead data_reads[] = {
18590 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18591 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18592 MockRead("hello world"),
18593 MockRead(SYNCHRONOUS, OK),
18594 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118595 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418596 session_deps_.socket_factory->AddSocketDataProvider(&data);
18597
18598 TestCompletionCallback callback;
18599
tfarina42834112016-09-22 13:38:2018600 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118601 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418602
18603 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118604 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418605
bnc691fda62016-08-12 00:43:1618606 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218607 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418608
wezca1070932016-05-26 20:30:5218609 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418610 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18611
18612 std::string response_data;
bnc691fda62016-08-12 00:43:1618613 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118614 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418615 EXPECT_EQ("hello world", response_data);
18616}
18617
bncd16676a2016-07-20 16:23:0118618TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918619 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218620 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918621 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218622 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418623
18624 HttpRequestInfo request;
18625 request.method = "POST";
18626 request.url = GURL("http://www.foo.com/");
18627 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018628 request.traffic_annotation =
18629 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418630
danakj1fd259a02016-04-16 03:17:0918631 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618632 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418633 // Send headers successfully, but get an error while sending the body.
18634 MockWrite data_writes[] = {
18635 MockWrite("POST / HTTP/1.1\r\n"
18636 "Host: www.foo.com\r\n"
18637 "Connection: keep-alive\r\n"
18638 "Content-Length: 3\r\n\r\n"),
18639 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18640 };
18641
18642 MockRead data_reads[] = {
18643 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18644 MockRead("hello world"),
18645 MockRead(SYNCHRONOUS, OK),
18646 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118647 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418648 session_deps_.socket_factory->AddSocketDataProvider(&data);
18649
18650 TestCompletionCallback callback;
18651
tfarina42834112016-09-22 13:38:2018652 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118653 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418654
18655 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118656 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418657}
18658
bncd16676a2016-07-20 16:23:0118659TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418660 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918661 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218662 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918663 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218664 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418665
18666 HttpRequestInfo request;
18667 request.method = "POST";
18668 request.url = GURL("http://www.foo.com/");
18669 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018670 request.traffic_annotation =
18671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418672
danakj1fd259a02016-04-16 03:17:0918673 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418675 // Send headers successfully, but get an error while sending the body.
18676 MockWrite data_writes[] = {
18677 MockWrite("POST / HTTP/1.1\r\n"
18678 "Host: www.foo.com\r\n"
18679 "Connection: keep-alive\r\n"
18680 "Content-Length: 3\r\n\r\n"),
18681 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18682 };
18683
18684 MockRead data_reads[] = {
18685 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18686 MockRead("HTTP/1.0 302 Redirect\r\n"),
18687 MockRead("Location: http://somewhere-else.com/\r\n"),
18688 MockRead("Content-Length: 0\r\n\r\n"),
18689 MockRead(SYNCHRONOUS, OK),
18690 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118691 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418692 session_deps_.socket_factory->AddSocketDataProvider(&data);
18693
18694 TestCompletionCallback callback;
18695
tfarina42834112016-09-22 13:38:2018696 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118697 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418698
18699 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118700 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418701}
18702
bncd16676a2016-07-20 16:23:0118703TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918704 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218705 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918706 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218707 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418708
18709 HttpRequestInfo request;
18710 request.method = "POST";
18711 request.url = GURL("http://www.foo.com/");
18712 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018713 request.traffic_annotation =
18714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418715
danakj1fd259a02016-04-16 03:17:0918716 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618717 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418718 // Send headers successfully, but get an error while sending the body.
18719 MockWrite data_writes[] = {
18720 MockWrite("POST / HTTP/1.1\r\n"
18721 "Host: www.foo.com\r\n"
18722 "Connection: keep-alive\r\n"
18723 "Content-Length: 3\r\n\r\n"),
18724 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18725 };
18726
18727 MockRead data_reads[] = {
18728 MockRead("HTTP 0.9 rocks!"),
18729 MockRead(SYNCHRONOUS, OK),
18730 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118731 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418732 session_deps_.socket_factory->AddSocketDataProvider(&data);
18733
18734 TestCompletionCallback callback;
18735
tfarina42834112016-09-22 13:38:2018736 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118737 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418738
18739 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118740 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418741}
18742
bncd16676a2016-07-20 16:23:0118743TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0918744 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218745 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918746 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218747 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418748
18749 HttpRequestInfo request;
18750 request.method = "POST";
18751 request.url = GURL("http://www.foo.com/");
18752 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018753 request.traffic_annotation =
18754 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418755
danakj1fd259a02016-04-16 03:17:0918756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618757 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418758 // Send headers successfully, but get an error while sending the body.
18759 MockWrite data_writes[] = {
18760 MockWrite("POST / HTTP/1.1\r\n"
18761 "Host: www.foo.com\r\n"
18762 "Connection: keep-alive\r\n"
18763 "Content-Length: 3\r\n\r\n"),
18764 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18765 };
18766
18767 MockRead data_reads[] = {
18768 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
18769 MockRead(SYNCHRONOUS, OK),
18770 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118771 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418772 session_deps_.socket_factory->AddSocketDataProvider(&data);
18773
18774 TestCompletionCallback callback;
18775
tfarina42834112016-09-22 13:38:2018776 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118777 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418778
18779 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118780 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418781}
18782
Bence Békydca6bd92018-01-30 13:43:0618783#if BUILDFLAG(ENABLE_WEBSOCKETS)
18784
18785namespace {
18786
18787void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18788 headers->SetHeader("Connection", "Upgrade");
18789 headers->SetHeader("Upgrade", "websocket");
18790 headers->SetHeader("Origin", "http://www.example.org");
18791 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618792}
18793
18794} // namespace
18795
18796TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118797 for (bool secure : {true, false}) {
18798 MockWrite data_writes[] = {
18799 MockWrite("GET / HTTP/1.1\r\n"
18800 "Host: www.example.org\r\n"
18801 "Connection: Upgrade\r\n"
18802 "Upgrade: websocket\r\n"
18803 "Origin: http://www.example.org\r\n"
18804 "Sec-WebSocket-Version: 13\r\n"
18805 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18806 "Sec-WebSocket-Extensions: permessage-deflate; "
18807 "client_max_window_bits\r\n\r\n")};
18808
18809 MockRead data_reads[] = {
18810 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18811 "Upgrade: websocket\r\n"
18812 "Connection: Upgrade\r\n"
18813 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18814
Ryan Sleevib8d7ea02018-05-07 20:01:0118815 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118816 session_deps_.socket_factory->AddSocketDataProvider(&data);
18817 SSLSocketDataProvider ssl(ASYNC, OK);
18818 if (secure)
18819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618820
18821 HttpRequestInfo request;
18822 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118823 request.url =
18824 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18825 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1018826 request.traffic_annotation =
18827 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618828
Bence Béky2fcf4fa2018-04-06 20:06:0118829 TestWebSocketHandshakeStreamCreateHelper
18830 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518831
Bence Béky2fcf4fa2018-04-06 20:06:0118832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618833 HttpNetworkTransaction trans(LOW, session.get());
18834 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118835 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618836
18837 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118838 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618840
Bence Béky2fcf4fa2018-04-06 20:06:0118841 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18842 ASSERT_TRUE(stream_request);
18843 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18844 stream_request->websocket_handshake_stream_create_helper());
18845
18846 rv = callback.WaitForResult();
18847 EXPECT_THAT(rv, IsOk());
18848
18849 EXPECT_TRUE(data.AllReadDataConsumed());
18850 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618851 }
18852}
18853
Adam Rice425cf122015-01-19 06:18:2418854// Verify that proxy headers are not sent to the destination server when
18855// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118856TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418857 HttpRequestInfo request;
18858 request.method = "GET";
bncce36dca22015-04-21 22:11:2318859 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018860 request.traffic_annotation =
18861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418862 AddWebSocketHeaders(&request.extra_headers);
18863
18864 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918865 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5618866 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4918867 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418868
danakj1fd259a02016-04-16 03:17:0918869 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418870
18871 // Since a proxy is configured, try to establish a tunnel.
18872 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718873 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18874 "Host: www.example.org:443\r\n"
18875 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418876
18877 // After calling trans->RestartWithAuth(), this is the request we should
18878 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718879 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18880 "Host: www.example.org:443\r\n"
18881 "Proxy-Connection: keep-alive\r\n"
18882 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418883
rsleevidb16bb02015-11-12 23:47:1718884 MockWrite("GET / HTTP/1.1\r\n"
18885 "Host: www.example.org\r\n"
18886 "Connection: Upgrade\r\n"
18887 "Upgrade: websocket\r\n"
18888 "Origin: http://www.example.org\r\n"
18889 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518890 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18891 "Sec-WebSocket-Extensions: permessage-deflate; "
18892 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418893
18894 // The proxy responds to the connect with a 407, using a persistent
18895 // connection.
18896 MockRead data_reads[] = {
18897 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518898 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18899 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18900 "Content-Length: 0\r\n"
18901 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418902
18903 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18904
Bence Béky8d1c6052018-02-07 12:48:1518905 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18906 "Upgrade: websocket\r\n"
18907 "Connection: Upgrade\r\n"
18908 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418909
Ryan Sleevib8d7ea02018-05-07 20:01:0118910 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418911 session_deps_.socket_factory->AddSocketDataProvider(&data);
18912 SSLSocketDataProvider ssl(ASYNC, OK);
18913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18914
Bence Béky8d1c6052018-02-07 12:48:1518915 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18916
bnc87dcefc2017-05-25 12:47:5818917 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918918 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418919 trans->SetWebSocketHandshakeStreamCreateHelper(
18920 &websocket_stream_create_helper);
18921
18922 {
18923 TestCompletionCallback callback;
18924
tfarina42834112016-09-22 13:38:2018925 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118926 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418927
18928 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118929 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418930 }
18931
18932 const HttpResponseInfo* response = trans->GetResponseInfo();
18933 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218934 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418935 EXPECT_EQ(407, response->headers->response_code());
18936
18937 {
18938 TestCompletionCallback callback;
18939
18940 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18941 callback.callback());
robpercival214763f2016-07-01 23:27:0118942 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418943
18944 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118945 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418946 }
18947
18948 response = trans->GetResponseInfo();
18949 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218950 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418951
18952 EXPECT_EQ(101, response->headers->response_code());
18953
18954 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1118955 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2418956}
18957
18958// Verify that proxy headers are not sent to the destination server when
18959// establishing a tunnel for an insecure WebSocket connection.
18960// This requires the authentication info to be injected into the auth cache
18961// due to crbug.com/395064
18962// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118963TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418964 HttpRequestInfo request;
18965 request.method = "GET";
bncce36dca22015-04-21 22:11:2318966 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018967 request.traffic_annotation =
18968 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418969 AddWebSocketHeaders(&request.extra_headers);
18970
18971 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918972 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5618973 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4918974 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418975
danakj1fd259a02016-04-16 03:17:0918976 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418977
18978 MockWrite data_writes[] = {
18979 // Try to establish a tunnel for the WebSocket connection, with
18980 // credentials. Because WebSockets have a separate set of socket pools,
18981 // they cannot and will not use the same TCP/IP connection as the
18982 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518983 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18984 "Host: www.example.org:80\r\n"
18985 "Proxy-Connection: keep-alive\r\n"
18986 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418987
Bence Béky8d1c6052018-02-07 12:48:1518988 MockWrite("GET / HTTP/1.1\r\n"
18989 "Host: www.example.org\r\n"
18990 "Connection: Upgrade\r\n"
18991 "Upgrade: websocket\r\n"
18992 "Origin: http://www.example.org\r\n"
18993 "Sec-WebSocket-Version: 13\r\n"
18994 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18995 "Sec-WebSocket-Extensions: permessage-deflate; "
18996 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418997
18998 MockRead data_reads[] = {
18999 // HTTP CONNECT with credentials.
19000 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19001
19002 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1519003 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19004 "Upgrade: websocket\r\n"
19005 "Connection: Upgrade\r\n"
19006 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419007
Ryan Sleevib8d7ea02018-05-07 20:01:0119008 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419009 session_deps_.socket_factory->AddSocketDataProvider(&data);
19010
19011 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3319012 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2619013 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
19014 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2419015
Bence Béky8d1c6052018-02-07 12:48:1519016 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19017
bnc87dcefc2017-05-25 12:47:5819018 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919019 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419020 trans->SetWebSocketHandshakeStreamCreateHelper(
19021 &websocket_stream_create_helper);
19022
19023 TestCompletionCallback callback;
19024
tfarina42834112016-09-22 13:38:2019025 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119026 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419027
19028 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119029 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419030
19031 const HttpResponseInfo* response = trans->GetResponseInfo();
19032 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219033 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419034
19035 EXPECT_EQ(101, response->headers->response_code());
19036
19037 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119038 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419039}
19040
Matt Menke1d6093e32019-03-22 17:33:4319041// WebSockets over QUIC is not supported, including over QUIC proxies.
19042TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
19043 for (bool secure : {true, false}) {
19044 SCOPED_TRACE(secure);
19045 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619046 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke1d6093e32019-03-22 17:33:4319047 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
19048 session_deps_.enable_quic = true;
19049
19050 HttpRequestInfo request;
19051 request.url =
19052 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19053 AddWebSocketHeaders(&request.extra_headers);
19054 request.traffic_annotation =
19055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19056
19057 TestWebSocketHandshakeStreamCreateHelper
19058 websocket_handshake_stream_create_helper;
19059
19060 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19061 HttpNetworkTransaction trans(LOW, session.get());
19062 trans.SetWebSocketHandshakeStreamCreateHelper(
19063 &websocket_handshake_stream_create_helper);
19064
19065 TestCompletionCallback callback;
19066 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19067 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19068
19069 rv = callback.WaitForResult();
19070 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
19071 }
19072}
19073
Bence Békydca6bd92018-01-30 13:43:0619074#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
19075
bncd16676a2016-07-20 16:23:0119076TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0919077 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219078 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919079 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219080 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219081
19082 HttpRequestInfo request;
19083 request.method = "POST";
19084 request.url = GURL("http://www.foo.com/");
19085 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019086 request.traffic_annotation =
19087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219088
danakj1fd259a02016-04-16 03:17:0919089 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619090 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219091 MockWrite data_writes[] = {
19092 MockWrite("POST / HTTP/1.1\r\n"
19093 "Host: www.foo.com\r\n"
19094 "Connection: keep-alive\r\n"
19095 "Content-Length: 3\r\n\r\n"),
19096 MockWrite("foo"),
19097 };
19098
19099 MockRead data_reads[] = {
19100 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19101 MockRead(SYNCHRONOUS, OK),
19102 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119103 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219104 session_deps_.socket_factory->AddSocketDataProvider(&data);
19105
19106 TestCompletionCallback callback;
19107
19108 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019109 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119110 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219111
19112 std::string response_data;
bnc691fda62016-08-12 00:43:1619113 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219114
Ryan Sleevib8d7ea02018-05-07 20:01:0119115 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19116 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219117}
19118
bncd16676a2016-07-20 16:23:0119119TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919120 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219121 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919122 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219123 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219124
19125 HttpRequestInfo request;
19126 request.method = "POST";
19127 request.url = GURL("http://www.foo.com/");
19128 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019129 request.traffic_annotation =
19130 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219131
danakj1fd259a02016-04-16 03:17:0919132 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619133 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219134 MockWrite data_writes[] = {
19135 MockWrite("POST / HTTP/1.1\r\n"
19136 "Host: www.foo.com\r\n"
19137 "Connection: keep-alive\r\n"
19138 "Content-Length: 3\r\n\r\n"),
19139 MockWrite("foo"),
19140 };
19141
19142 MockRead data_reads[] = {
19143 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19144 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19145 MockRead(SYNCHRONOUS, OK),
19146 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119147 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219148 session_deps_.socket_factory->AddSocketDataProvider(&data);
19149
19150 TestCompletionCallback callback;
19151
19152 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019153 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119154 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219155
19156 std::string response_data;
bnc691fda62016-08-12 00:43:1619157 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219158
Ryan Sleevib8d7ea02018-05-07 20:01:0119159 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19160 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219161}
19162
bncd16676a2016-07-20 16:23:0119163TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219164 ChunkedUploadDataStream upload_data_stream(0);
19165
19166 HttpRequestInfo request;
19167 request.method = "POST";
19168 request.url = GURL("http://www.foo.com/");
19169 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1019170 request.traffic_annotation =
19171 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219172
danakj1fd259a02016-04-16 03:17:0919173 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619174 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219175 // Send headers successfully, but get an error while sending the body.
19176 MockWrite data_writes[] = {
19177 MockWrite("POST / HTTP/1.1\r\n"
19178 "Host: www.foo.com\r\n"
19179 "Connection: keep-alive\r\n"
19180 "Transfer-Encoding: chunked\r\n\r\n"),
19181 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19182 };
19183
19184 MockRead data_reads[] = {
19185 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19186 MockRead(SYNCHRONOUS, OK),
19187 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119188 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219189 session_deps_.socket_factory->AddSocketDataProvider(&data);
19190
19191 TestCompletionCallback callback;
19192
19193 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019194 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219195
19196 base::RunLoop().RunUntilIdle();
19197 upload_data_stream.AppendData("f", 1, false);
19198
19199 base::RunLoop().RunUntilIdle();
19200 upload_data_stream.AppendData("oo", 2, true);
19201
robpercival214763f2016-07-01 23:27:0119202 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219203
19204 std::string response_data;
bnc691fda62016-08-12 00:43:1619205 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219206
Ryan Sleevib8d7ea02018-05-07 20:01:0119207 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19208 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219209}
19210
eustasc7d27da2017-04-06 10:33:2019211void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19212 const std::string& accept_encoding,
19213 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319214 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019215 bool should_match) {
19216 HttpRequestInfo request;
19217 request.method = "GET";
19218 request.url = GURL("http://www.foo.com/");
19219 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19220 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1019221 request.traffic_annotation =
19222 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019223
19224 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19225 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19226 // Send headers successfully, but get an error while sending the body.
19227 MockWrite data_writes[] = {
19228 MockWrite("GET / HTTP/1.1\r\n"
19229 "Host: www.foo.com\r\n"
19230 "Connection: keep-alive\r\n"
19231 "Accept-Encoding: "),
19232 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19233 };
19234
sky50576f32017-05-01 19:28:0319235 std::string response_code = "200 OK";
19236 std::string extra;
19237 if (!location.empty()) {
19238 response_code = "301 Redirect\r\nLocation: ";
19239 response_code.append(location);
19240 }
19241
eustasc7d27da2017-04-06 10:33:2019242 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319243 MockRead("HTTP/1.0 "),
19244 MockRead(response_code.data()),
19245 MockRead("\r\nContent-Encoding: "),
19246 MockRead(content_encoding.data()),
19247 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019248 MockRead(SYNCHRONOUS, OK),
19249 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119250 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019251 session_deps->socket_factory->AddSocketDataProvider(&data);
19252
19253 TestCompletionCallback callback;
19254
19255 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19256 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19257
19258 rv = callback.WaitForResult();
19259 if (should_match) {
19260 EXPECT_THAT(rv, IsOk());
19261 } else {
19262 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19263 }
19264}
19265
19266TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319267 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019268}
19269
19270TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319271 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19272 true);
eustasc7d27da2017-04-06 10:33:2019273}
19274
19275TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19276 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319277 "", false);
19278}
19279
19280TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19281 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19282 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019283}
19284
xunjieli96f2a402017-06-05 17:24:2719285TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19286 ProxyConfig proxy_config;
19287 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19288 proxy_config.set_pac_mandatory(true);
19289 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619290 session_deps_.proxy_resolution_service.reset(
19291 new ConfiguredProxyResolutionService(
19292 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19293 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919294 std::make_unique<FailingProxyResolverFactory>(), nullptr,
19295 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719296
19297 HttpRequestInfo request;
19298 request.method = "GET";
19299 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019300 request.traffic_annotation =
19301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719302
19303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19304 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19305
19306 TestCompletionCallback callback;
19307
19308 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19309 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19310 EXPECT_THAT(callback.WaitForResult(),
19311 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19312}
19313
19314TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19315 ProxyConfig proxy_config;
19316 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19317 proxy_config.set_pac_mandatory(true);
19318 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19319 new MockAsyncProxyResolverFactory(false);
19320 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619321 session_deps_.proxy_resolution_service.reset(
19322 new ConfiguredProxyResolutionService(
19323 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19324 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919325 base::WrapUnique(proxy_resolver_factory), nullptr,
19326 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719327 HttpRequestInfo request;
19328 request.method = "GET";
19329 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019330 request.traffic_annotation =
19331 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719332
19333 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19334 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19335
19336 TestCompletionCallback callback;
19337 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19338 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19339
19340 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19341 ERR_FAILED, &resolver);
19342 EXPECT_THAT(callback.WaitForResult(),
19343 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19344}
19345
19346TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919347 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619348 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919349 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719350 session_deps_.enable_quic = false;
19351 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19352
19353 HttpRequestInfo request;
19354 request.method = "GET";
19355 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1019356 request.traffic_annotation =
19357 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719358
19359 TestCompletionCallback callback;
19360 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19361 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19362 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19363
19364 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19365}
19366
Douglas Creager3cb042052018-11-06 23:08:5219367//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419368// Reporting tests
19369
19370#if BUILDFLAG(ENABLE_REPORTING)
19371class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19372 protected:
19373 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619374 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419375 auto test_reporting_context = std::make_unique<TestReportingContext>(
19376 &clock_, &tick_clock_, ReportingPolicy());
19377 test_reporting_context_ = test_reporting_context.get();
19378 session_deps_.reporting_service =
19379 ReportingService::CreateForTesting(std::move(test_reporting_context));
19380 }
19381
19382 TestReportingContext* reporting_context() const {
19383 return test_reporting_context_;
19384 }
19385
19386 void clear_reporting_service() {
19387 session_deps_.reporting_service.reset();
19388 test_reporting_context_ = nullptr;
19389 }
19390
19391 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219392 void RequestPolicy(CertStatus cert_status = 0) {
19393 HttpRequestInfo request;
19394 request.method = "GET";
19395 request.url = GURL(url_);
19396 request.traffic_annotation =
19397 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19398
Lily Chend3930e72019-03-01 19:31:1119399 MockWrite data_writes[] = {
19400 MockWrite("GET / HTTP/1.1\r\n"
19401 "Host: www.example.org\r\n"
19402 "Connection: keep-alive\r\n\r\n"),
19403 };
Douglas Creager134b52e2018-11-09 18:00:1419404 MockRead data_reads[] = {
19405 MockRead("HTTP/1.0 200 OK\r\n"),
19406 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19407 "\"endpoints\": [{\"url\": "
19408 "\"https://www.example.org/upload/\"}]}\r\n"),
19409 MockRead("\r\n"),
19410 MockRead("hello world"),
19411 MockRead(SYNCHRONOUS, OK),
19412 };
Douglas Creager134b52e2018-11-09 18:00:1419413
Lily Chenfec60d92019-01-24 01:16:4219414 StaticSocketDataProvider reads(data_reads, data_writes);
19415 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419416
19417 SSLSocketDataProvider ssl(ASYNC, OK);
19418 if (request.url.SchemeIsCryptographic()) {
19419 ssl.ssl_info.cert =
19420 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19421 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219422 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19424 }
19425
Douglas Creager134b52e2018-11-09 18:00:1419426 TestCompletionCallback callback;
19427 auto session = CreateSession(&session_deps_);
19428 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19429 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219430 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419431 }
19432
19433 protected:
19434 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419435
19436 private:
19437 TestReportingContext* test_reporting_context_;
19438};
19439
19440TEST_F(HttpNetworkTransactionReportingTest,
19441 DontProcessReportToHeaderNoService) {
19442 base::HistogramTester histograms;
19443 clear_reporting_service();
19444 RequestPolicy();
19445 histograms.ExpectBucketCount(
19446 ReportingHeaderParser::kHeaderOutcomeHistogram,
19447 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
19448}
19449
19450TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
19451 base::HistogramTester histograms;
19452 url_ = "http://www.example.org/";
19453 RequestPolicy();
19454 histograms.ExpectBucketCount(
19455 ReportingHeaderParser::kHeaderOutcomeHistogram,
19456 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19457}
19458
19459TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19460 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419461 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019462 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419463 reporting_context()->cache()->GetEndpointForTesting(
Lily Chenad5dd0802020-03-10 21:58:0919464 ReportingEndpointGroupKey(
19465 NetworkIsolationKey(),
19466 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
Lily Chenefb6fcf2019-04-19 04:17:5419467 GURL("https://www.example.org/upload/"));
19468 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419469}
19470
19471TEST_F(HttpNetworkTransactionReportingTest,
19472 DontProcessReportToHeaderInvalidHttps) {
19473 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219474 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19475 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1419476 histograms.ExpectBucketCount(
19477 ReportingHeaderParser::kHeaderOutcomeHistogram,
19478 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
19479}
19480#endif // BUILDFLAG(ENABLE_REPORTING)
19481
19482//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219483// Network Error Logging tests
19484
19485#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219486namespace {
19487
19488const char kUserAgent[] = "Mozilla/1.0";
19489const char kReferrer[] = "https://www.referrer.org/";
19490
19491} // namespace
19492
Douglas Creager3cb042052018-11-06 23:08:5219493class HttpNetworkTransactionNetworkErrorLoggingTest
19494 : public HttpNetworkTransactionTest {
19495 protected:
19496 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619497 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219498 auto network_error_logging_service =
19499 std::make_unique<TestNetworkErrorLoggingService>();
19500 test_network_error_logging_service_ = network_error_logging_service.get();
19501 session_deps_.network_error_logging_service =
19502 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219503
19504 extra_headers_.SetHeader("User-Agent", kUserAgent);
19505 extra_headers_.SetHeader("Referer", kReferrer);
19506
19507 request_.method = "GET";
19508 request_.url = GURL(url_);
19509 request_.extra_headers = extra_headers_;
19510 request_.reporting_upload_depth = reporting_upload_depth_;
19511 request_.traffic_annotation =
19512 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219513 }
19514
19515 TestNetworkErrorLoggingService* network_error_logging_service() const {
19516 return test_network_error_logging_service_;
19517 }
19518
19519 void clear_network_error_logging_service() {
19520 session_deps_.network_error_logging_service.reset();
19521 test_network_error_logging_service_ = nullptr;
19522 }
19523
19524 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219525 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619526 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319527 MockWrite data_writes[] = {
19528 MockWrite("GET / HTTP/1.1\r\n"
19529 "Host: www.example.org\r\n"
19530 "Connection: keep-alive\r\n"),
19531 MockWrite(ASYNC, extra_header_string.data(),
19532 extra_header_string.size()),
19533 };
Lily Chend3930e72019-03-01 19:31:1119534 MockRead data_reads[] = {
19535 MockRead("HTTP/1.0 200 OK\r\n"),
19536 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19537 MockRead("\r\n"),
19538 MockRead("hello world"),
19539 MockRead(SYNCHRONOUS, OK),
19540 };
Douglas Creager3cb042052018-11-06 23:08:5219541
Lily Chenfec60d92019-01-24 01:16:4219542 StaticSocketDataProvider reads(data_reads, data_writes);
19543 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219544
19545 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219546 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219547 ssl.ssl_info.cert =
19548 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19549 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219550 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219551 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19552 }
19553
Douglas Creager3cb042052018-11-06 23:08:5219554 TestCompletionCallback callback;
19555 auto session = CreateSession(&session_deps_);
19556 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219557 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19558 EXPECT_THAT(callback.GetResult(rv), IsOk());
19559
19560 std::string response_data;
19561 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19562 EXPECT_EQ("hello world", response_data);
19563 }
19564
19565 void CheckReport(size_t index,
19566 int status_code,
19567 int error_type,
19568 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19569 ASSERT_LT(index, network_error_logging_service()->errors().size());
19570
19571 const NetworkErrorLoggingService::RequestDetails& error =
19572 network_error_logging_service()->errors()[index];
19573 EXPECT_EQ(url_, error.uri);
19574 EXPECT_EQ(kReferrer, error.referrer);
19575 EXPECT_EQ(kUserAgent, error.user_agent);
19576 EXPECT_EQ(server_ip, error.server_ip);
19577 EXPECT_EQ("http/1.1", error.protocol);
19578 EXPECT_EQ("GET", error.method);
19579 EXPECT_EQ(status_code, error.status_code);
19580 EXPECT_EQ(error_type, error.type);
19581 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219582 }
19583
19584 protected:
19585 std::string url_ = "https://www.example.org/";
19586 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219587 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619588 HttpRequestHeaders extra_headers_;
19589 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219590
19591 private:
19592 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19593};
19594
19595TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19596 DontProcessNelHeaderNoService) {
19597 base::HistogramTester histograms;
19598 clear_network_error_logging_service();
19599 RequestPolicy();
19600 histograms.ExpectBucketCount(
19601 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19602 NetworkErrorLoggingService::HeaderOutcome::
19603 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
19604 1);
19605}
19606
19607TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19608 DontProcessNelHeaderHttp) {
19609 base::HistogramTester histograms;
19610 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219611 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219612 RequestPolicy();
19613 histograms.ExpectBucketCount(
19614 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19615 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19616}
19617
Lily Chen90ae93cc2019-02-14 01:15:3919618// Don't set NEL policies received on a proxied connection.
19619TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19620 DontProcessNelHeaderProxy) {
19621 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619622 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3919623 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1419624 RecordingBoundTestNetLog log;
Lily Chen90ae93cc2019-02-14 01:15:3919625 session_deps_.net_log = log.bound().net_log();
19626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19627
19628 HttpRequestInfo request;
19629 request.method = "GET";
19630 request.url = GURL("https://www.example.org/");
19631 request.traffic_annotation =
19632 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19633
19634 // Since we have proxy, should try to establish tunnel.
19635 MockWrite data_writes1[] = {
19636 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19637 "Host: www.example.org:443\r\n"
19638 "Proxy-Connection: keep-alive\r\n\r\n"),
19639
19640 MockWrite("GET / HTTP/1.1\r\n"
19641 "Host: www.example.org\r\n"
19642 "Connection: keep-alive\r\n\r\n"),
19643 };
19644
19645 MockRead data_reads1[] = {
19646 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19647
19648 MockRead("HTTP/1.1 200 OK\r\n"),
19649 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19651 MockRead("Content-Length: 100\r\n\r\n"),
19652 MockRead(SYNCHRONOUS, OK),
19653 };
19654
19655 StaticSocketDataProvider data1(data_reads1, data_writes1);
19656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19657 SSLSocketDataProvider ssl(ASYNC, OK);
19658 ssl.ssl_info.cert =
19659 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19660 ASSERT_TRUE(ssl.ssl_info.cert);
19661 ssl.ssl_info.cert_status = 0;
19662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19663
19664 TestCompletionCallback callback1;
19665 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19666
19667 int rv = trans.Start(&request, callback1.callback(), log.bound());
19668 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19669
19670 rv = callback1.WaitForResult();
19671 EXPECT_THAT(rv, IsOk());
19672
19673 const HttpResponseInfo* response = trans.GetResponseInfo();
19674 ASSERT_TRUE(response);
19675 EXPECT_EQ(200, response->headers->response_code());
19676 EXPECT_TRUE(response->was_fetched_via_proxy);
19677
19678 // No NEL header was set.
19679 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19680}
19681
Douglas Creager3cb042052018-11-06 23:08:5219682TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19683 RequestPolicy();
19684 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19685 const auto& header = network_error_logging_service()->headers()[0];
19686 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19687 header.origin);
19688 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19689 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19690}
19691
19692TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19693 DontProcessNelHeaderInvalidHttps) {
19694 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219695 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19696 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5219697 histograms.ExpectBucketCount(
19698 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19699 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
19700 1);
19701}
Douglas Creageref5eecdc2018-11-09 20:50:3619702
Lily Chenfec60d92019-01-24 01:16:4219703TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3619704 RequestPolicy();
19705 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219706 CheckReport(0 /* index */, 200 /* status_code */, OK);
19707}
19708
19709TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19710 CreateReportErrorAfterStart) {
19711 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19712 auto trans =
19713 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19714
19715 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
19716 StaticSocketDataProvider data;
19717 data.set_connect_data(mock_connect);
19718 session_deps_.socket_factory->AddSocketDataProvider(&data);
19719
19720 TestCompletionCallback callback;
19721
19722 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19723 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19724
19725 trans.reset();
19726
19727 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19728 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19729 IPAddress() /* server_ip */);
19730}
19731
19732// Same as above except the error is ASYNC
19733TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19734 CreateReportErrorAfterStartAsync) {
19735 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19736 auto trans =
19737 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19738
19739 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
19740 StaticSocketDataProvider data;
19741 data.set_connect_data(mock_connect);
19742 session_deps_.socket_factory->AddSocketDataProvider(&data);
19743
19744 TestCompletionCallback callback;
19745
19746 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19747 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19748
19749 trans.reset();
19750
19751 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19752 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19753 IPAddress() /* server_ip */);
19754}
19755
19756TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19757 CreateReportReadBodyError) {
19758 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319759 MockWrite data_writes[] = {
19760 MockWrite("GET / HTTP/1.1\r\n"
19761 "Host: www.example.org\r\n"
19762 "Connection: keep-alive\r\n"),
19763 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19764 };
Lily Chend3930e72019-03-01 19:31:1119765 MockRead data_reads[] = {
19766 MockRead("HTTP/1.0 200 OK\r\n"),
19767 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19768 MockRead("hello world"),
19769 MockRead(SYNCHRONOUS, OK),
19770 };
Lily Chenfec60d92019-01-24 01:16:4219771
19772 StaticSocketDataProvider reads(data_reads, data_writes);
19773 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19774
19775 SSLSocketDataProvider ssl(ASYNC, OK);
19776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19777
19778 // Log start time
19779 base::TimeTicks start_time = base::TimeTicks::Now();
19780
19781 TestCompletionCallback callback;
19782 auto session = CreateSession(&session_deps_);
19783 auto trans =
19784 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19785 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19786 EXPECT_THAT(callback.GetResult(rv), IsOk());
19787
19788 const HttpResponseInfo* response = trans->GetResponseInfo();
19789 ASSERT_TRUE(response);
19790
19791 EXPECT_TRUE(response->headers);
19792 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19793
19794 std::string response_data;
19795 rv = ReadTransaction(trans.get(), &response_data);
19796 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19797
19798 trans.reset();
19799
19800 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19801
19802 CheckReport(0 /* index */, 200 /* status_code */,
19803 ERR_CONTENT_LENGTH_MISMATCH);
19804 const NetworkErrorLoggingService::RequestDetails& error =
19805 network_error_logging_service()->errors()[0];
19806 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19807}
19808
19809// Same as above except the final read is ASYNC.
19810TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19811 CreateReportReadBodyErrorAsync) {
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(ASYNC, 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
19863TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19864 CreateReportRestartWithAuth) {
19865 std::string extra_header_string = extra_headers_.ToString();
19866 static const base::TimeDelta kSleepDuration =
19867 base::TimeDelta::FromMilliseconds(10);
19868
19869 MockWrite data_writes1[] = {
19870 MockWrite("GET / HTTP/1.1\r\n"
19871 "Host: www.example.org\r\n"
19872 "Connection: keep-alive\r\n"),
19873 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19874 };
19875
19876 MockRead data_reads1[] = {
19877 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19878 // Give a couple authenticate options (only the middle one is actually
19879 // supported).
19880 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19881 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19882 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19883 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19884 // Large content-length -- won't matter, as connection will be reset.
19885 MockRead("Content-Length: 10000\r\n\r\n"),
19886 MockRead(SYNCHRONOUS, ERR_FAILED),
19887 };
19888
19889 // After calling trans->RestartWithAuth(), this is the request we should
19890 // be issuing -- the final header line contains the credentials.
19891 MockWrite data_writes2[] = {
19892 MockWrite("GET / HTTP/1.1\r\n"
19893 "Host: www.example.org\r\n"
19894 "Connection: keep-alive\r\n"
19895 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19896 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19897 };
19898
19899 // Lastly, the server responds with the actual content.
19900 MockRead data_reads2[] = {
19901 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19902 MockRead("hello world"),
19903 MockRead(SYNCHRONOUS, OK),
19904 };
19905
19906 StaticSocketDataProvider data1(data_reads1, data_writes1);
19907 StaticSocketDataProvider data2(data_reads2, data_writes2);
19908 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19909 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19910
19911 SSLSocketDataProvider ssl1(ASYNC, OK);
19912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19913 SSLSocketDataProvider ssl2(ASYNC, OK);
19914 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19915
19916 base::TimeTicks start_time = base::TimeTicks::Now();
19917 base::TimeTicks restart_time;
19918
19919 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19920 auto trans =
19921 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19922
19923 TestCompletionCallback callback1;
19924
19925 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19926 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19927
19928 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19929
19930 TestCompletionCallback callback2;
19931
19932 // Wait 10 ms then restart with auth
19933 FastForwardBy(kSleepDuration);
19934 restart_time = base::TimeTicks::Now();
19935 rv =
19936 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19937 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19938
19939 std::string response_data;
19940 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19941 EXPECT_EQ("hello world", response_data);
19942
19943 trans.reset();
19944
19945 // One 401 report for the auth challenge, then a 200 report for the successful
19946 // retry. Note that we don't report the error draining the body, as the first
19947 // request already generated a report for the auth challenge.
19948 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19949
19950 // Check error report contents
19951 CheckReport(0 /* index */, 401 /* status_code */, OK);
19952 CheckReport(1 /* index */, 200 /* status_code */, OK);
19953
19954 const NetworkErrorLoggingService::RequestDetails& error1 =
19955 network_error_logging_service()->errors()[0];
19956 const NetworkErrorLoggingService::RequestDetails& error2 =
19957 network_error_logging_service()->errors()[1];
19958
19959 // Sanity-check elapsed time values
19960 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19961 // Check that the start time is refreshed when restarting with auth.
19962 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19963}
19964
19965// Same as above, except draining the body before restarting fails
19966// asynchronously.
19967TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19968 CreateReportRestartWithAuthAsync) {
19969 std::string extra_header_string = extra_headers_.ToString();
19970 static const base::TimeDelta kSleepDuration =
19971 base::TimeDelta::FromMilliseconds(10);
19972
19973 MockWrite data_writes1[] = {
19974 MockWrite("GET / HTTP/1.1\r\n"
19975 "Host: www.example.org\r\n"
19976 "Connection: keep-alive\r\n"),
19977 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19978 };
19979
19980 MockRead data_reads1[] = {
19981 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19982 // Give a couple authenticate options (only the middle one is actually
19983 // supported).
19984 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19986 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19987 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19988 // Large content-length -- won't matter, as connection will be reset.
19989 MockRead("Content-Length: 10000\r\n\r\n"),
19990 MockRead(ASYNC, ERR_FAILED),
19991 };
19992
19993 // After calling trans->RestartWithAuth(), this is the request we should
19994 // be issuing -- the final header line contains the credentials.
19995 MockWrite data_writes2[] = {
19996 MockWrite("GET / HTTP/1.1\r\n"
19997 "Host: www.example.org\r\n"
19998 "Connection: keep-alive\r\n"
19999 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20000 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20001 };
20002
20003 // Lastly, the server responds with the actual content.
20004 MockRead data_reads2[] = {
20005 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20006 MockRead("hello world"),
20007 MockRead(SYNCHRONOUS, OK),
20008 };
20009
20010 StaticSocketDataProvider data1(data_reads1, data_writes1);
20011 StaticSocketDataProvider data2(data_reads2, data_writes2);
20012 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20013 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20014
20015 SSLSocketDataProvider ssl1(ASYNC, OK);
20016 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20017 SSLSocketDataProvider ssl2(ASYNC, OK);
20018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20019
20020 base::TimeTicks start_time = base::TimeTicks::Now();
20021 base::TimeTicks restart_time;
20022
20023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20024 auto trans =
20025 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20026
20027 TestCompletionCallback callback1;
20028
20029 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20030 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20031
20032 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20033
20034 TestCompletionCallback callback2;
20035
20036 // Wait 10 ms then restart with auth
20037 FastForwardBy(kSleepDuration);
20038 restart_time = base::TimeTicks::Now();
20039 rv =
20040 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20041 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20042
20043 std::string response_data;
20044 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20045 EXPECT_EQ("hello world", response_data);
20046
20047 trans.reset();
20048
20049 // One 401 report for the auth challenge, then a 200 report for the successful
20050 // retry. Note that we don't report the error draining the body, as the first
20051 // request already generated a report for the auth challenge.
20052 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20053
20054 // Check error report contents
20055 CheckReport(0 /* index */, 401 /* status_code */, OK);
20056 CheckReport(1 /* index */, 200 /* status_code */, OK);
20057
20058 const NetworkErrorLoggingService::RequestDetails& error1 =
20059 network_error_logging_service()->errors()[0];
20060 const NetworkErrorLoggingService::RequestDetails& error2 =
20061 network_error_logging_service()->errors()[1];
20062
20063 // Sanity-check elapsed time values
20064 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20065 // Check that the start time is refreshed when restarting with auth.
20066 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20067}
20068
20069TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20070 CreateReportRetryKeepAliveConnectionReset) {
20071 std::string extra_header_string = extra_headers_.ToString();
20072 MockWrite data_writes1[] = {
20073 MockWrite("GET / HTTP/1.1\r\n"
20074 "Host: www.example.org\r\n"
20075 "Connection: keep-alive\r\n"),
20076 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20077 MockWrite("GET / HTTP/1.1\r\n"
20078 "Host: www.example.org\r\n"
20079 "Connection: keep-alive\r\n"),
20080 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20081 };
20082
20083 MockRead data_reads1[] = {
20084 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20085 MockRead("hello"),
20086 // Connection is reset
20087 MockRead(ASYNC, ERR_CONNECTION_RESET),
20088 };
20089
20090 // Successful retry
20091 MockRead data_reads2[] = {
20092 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20093 MockRead("world"),
20094 MockRead(ASYNC, OK),
20095 };
20096
20097 StaticSocketDataProvider data1(data_reads1, data_writes1);
20098 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20099 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20100 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20101
20102 SSLSocketDataProvider ssl1(ASYNC, OK);
20103 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20104 SSLSocketDataProvider ssl2(ASYNC, OK);
20105 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20106
20107 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20108 auto trans1 =
20109 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20110
20111 TestCompletionCallback callback1;
20112
20113 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20114 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20115
20116 std::string response_data;
20117 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20118 EXPECT_EQ("hello", response_data);
20119
20120 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20121
20122 auto trans2 =
20123 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20124
20125 TestCompletionCallback callback2;
20126
20127 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20128 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20129
20130 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20131 EXPECT_EQ("world", response_data);
20132
20133 trans1.reset();
20134 trans2.reset();
20135
20136 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20137 // the second request, then an OK report from the successful retry.
20138 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20139
20140 // Check error report contents
20141 CheckReport(0 /* index */, 200 /* status_code */, OK);
20142 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20143 CheckReport(2 /* index */, 200 /* status_code */, OK);
20144}
20145
20146TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20147 CreateReportRetryKeepAlive408) {
20148 std::string extra_header_string = extra_headers_.ToString();
20149 MockWrite data_writes1[] = {
20150 MockWrite("GET / HTTP/1.1\r\n"
20151 "Host: www.example.org\r\n"
20152 "Connection: keep-alive\r\n"),
20153 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20154 MockWrite("GET / HTTP/1.1\r\n"
20155 "Host: www.example.org\r\n"
20156 "Connection: keep-alive\r\n"),
20157 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20158 };
20159
20160 MockRead data_reads1[] = {
20161 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20162 MockRead("hello"),
20163 // 408 Request Timeout
20164 MockRead(SYNCHRONOUS,
20165 "HTTP/1.1 408 Request Timeout\r\n"
20166 "Connection: Keep-Alive\r\n"
20167 "Content-Length: 6\r\n\r\n"
20168 "Pickle"),
20169 };
20170
20171 // Successful retry
20172 MockRead data_reads2[] = {
20173 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20174 MockRead("world"),
20175 MockRead(ASYNC, OK),
20176 };
20177
20178 StaticSocketDataProvider data1(data_reads1, data_writes1);
20179 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20180 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20181 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20182
20183 SSLSocketDataProvider ssl1(ASYNC, OK);
20184 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20185 SSLSocketDataProvider ssl2(ASYNC, OK);
20186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20187
20188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20189 auto trans1 =
20190 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20191
20192 TestCompletionCallback callback1;
20193
20194 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20195 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20196
20197 std::string response_data;
20198 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20199 EXPECT_EQ("hello", response_data);
20200
20201 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20202
20203 auto trans2 =
20204 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20205
20206 TestCompletionCallback callback2;
20207
20208 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20209 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20210
20211 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20212 EXPECT_EQ("world", response_data);
20213
20214 trans1.reset();
20215 trans2.reset();
20216
20217 // One 200 report from first request, then a 408 report from
20218 // the second request, then a 200 report from the successful retry.
20219 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20220
20221 // Check error report contents
20222 CheckReport(0 /* index */, 200 /* status_code */, OK);
20223 CheckReport(1 /* index */, 408 /* status_code */, OK);
20224 CheckReport(2 /* index */, 200 /* status_code */, OK);
20225}
20226
20227TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20228 CreateReportRetry421WithoutConnectionPooling) {
20229 // Two hosts resolve to the same IP address.
20230 const std::string ip_addr = "1.2.3.4";
20231 IPAddress ip;
20232 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20233 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20234
20235 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20236 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20237 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20238
20239 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20240
20241 // Two requests on the first connection.
20242 spdy::SpdySerializedFrame req1(
20243 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20244 spdy_util_.UpdateWithStreamDestruction(1);
20245 spdy::SpdySerializedFrame req2(
20246 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20247 spdy::SpdySerializedFrame rst(
20248 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20249 MockWrite writes1[] = {
20250 CreateMockWrite(req1, 0),
20251 CreateMockWrite(req2, 3),
20252 CreateMockWrite(rst, 6),
20253 };
20254
20255 // The first one succeeds, the second gets error 421 Misdirected Request.
20256 spdy::SpdySerializedFrame resp1(
20257 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20258 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20259 spdy::SpdyHeaderBlock response_headers;
20260 response_headers[spdy::kHttp2StatusHeader] = "421";
20261 spdy::SpdySerializedFrame resp2(
20262 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20263 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20264 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20265
20266 MockConnect connect1(ASYNC, OK, peer_addr);
20267 SequencedSocketData data1(connect1, reads1, writes1);
20268 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20269
20270 AddSSLSocketData();
20271
20272 // Retry the second request on a second connection.
20273 SpdyTestUtil spdy_util2;
20274 spdy::SpdySerializedFrame req3(
20275 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20276 MockWrite writes2[] = {
20277 CreateMockWrite(req3, 0),
20278 };
20279
20280 spdy::SpdySerializedFrame resp3(
20281 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20282 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20283 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20284 MockRead(ASYNC, 0, 3)};
20285
20286 MockConnect connect2(ASYNC, OK, peer_addr);
20287 SequencedSocketData data2(connect2, reads2, writes2);
20288 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20289
20290 AddSSLSocketData();
20291
20292 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320293 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320294 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20295 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320296 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220297
20298 HttpRequestInfo request1;
20299 request1.method = "GET";
20300 request1.url = GURL("https://www.example.org/");
20301 request1.load_flags = 0;
20302 request1.traffic_annotation =
20303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20304 auto trans1 =
20305 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20306
Eric Orthf4db66a2019-02-19 21:35:3320307 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220308 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20309 EXPECT_THAT(callback.GetResult(rv), IsOk());
20310
20311 const HttpResponseInfo* response = trans1->GetResponseInfo();
20312 ASSERT_TRUE(response);
20313 ASSERT_TRUE(response->headers);
20314 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20315 EXPECT_TRUE(response->was_fetched_via_spdy);
20316 EXPECT_TRUE(response->was_alpn_negotiated);
20317 std::string response_data;
20318 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20319 EXPECT_EQ("hello!", response_data);
20320
20321 trans1.reset();
20322
20323 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20324
20325 HttpRequestInfo request2;
20326 request2.method = "GET";
20327 request2.url = GURL("https://mail.example.org/");
20328 request2.load_flags = 0;
20329 request2.traffic_annotation =
20330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20331 auto trans2 =
20332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20333
Matt Muellerd9342e3a2019-11-26 01:41:1420334 RecordingBoundTestNetLog log;
Lily Chenfec60d92019-01-24 01:16:4220335 rv = trans2->Start(&request2, callback.callback(), log.bound());
20336 EXPECT_THAT(callback.GetResult(rv), IsOk());
20337
20338 response = trans2->GetResponseInfo();
20339 ASSERT_TRUE(response);
20340 ASSERT_TRUE(response->headers);
20341 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20342 EXPECT_TRUE(response->was_fetched_via_spdy);
20343 EXPECT_TRUE(response->was_alpn_negotiated);
20344 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20345 EXPECT_EQ("hello!", response_data);
20346
20347 trans2.reset();
20348
20349 // One 200 report from the first request, then a 421 report from the
20350 // second request, then a 200 report from the successful retry.
20351 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20352
20353 // Check error report contents
20354 const NetworkErrorLoggingService::RequestDetails& error1 =
20355 network_error_logging_service()->errors()[0];
20356 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20357 EXPECT_TRUE(error1.referrer.is_empty());
20358 EXPECT_EQ("", error1.user_agent);
20359 EXPECT_EQ(ip, error1.server_ip);
20360 EXPECT_EQ("h2", error1.protocol);
20361 EXPECT_EQ("GET", error1.method);
20362 EXPECT_EQ(200, error1.status_code);
20363 EXPECT_EQ(OK, error1.type);
20364 EXPECT_EQ(0, error1.reporting_upload_depth);
20365
20366 const NetworkErrorLoggingService::RequestDetails& error2 =
20367 network_error_logging_service()->errors()[1];
20368 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20369 EXPECT_TRUE(error2.referrer.is_empty());
20370 EXPECT_EQ("", error2.user_agent);
20371 EXPECT_EQ(ip, error2.server_ip);
20372 EXPECT_EQ("h2", error2.protocol);
20373 EXPECT_EQ("GET", error2.method);
20374 EXPECT_EQ(421, error2.status_code);
20375 EXPECT_EQ(OK, error2.type);
20376 EXPECT_EQ(0, error2.reporting_upload_depth);
20377
20378 const NetworkErrorLoggingService::RequestDetails& error3 =
20379 network_error_logging_service()->errors()[2];
20380 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20381 EXPECT_TRUE(error3.referrer.is_empty());
20382 EXPECT_EQ("", error3.user_agent);
20383 EXPECT_EQ(ip, error3.server_ip);
20384 EXPECT_EQ("h2", error3.protocol);
20385 EXPECT_EQ("GET", error3.method);
20386 EXPECT_EQ(200, error3.status_code);
20387 EXPECT_EQ(OK, error3.type);
20388 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620389}
20390
Lily Chend3930e72019-03-01 19:31:1120391TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20392 CreateReportCancelAfterStart) {
20393 StaticSocketDataProvider data;
20394 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20395 session_deps_.socket_factory->AddSocketDataProvider(&data);
20396
20397 TestCompletionCallback callback;
20398 auto session = CreateSession(&session_deps_);
20399 auto trans =
20400 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20401 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20402 EXPECT_EQ(rv, ERR_IO_PENDING);
20403
20404 // Cancel after start.
20405 trans.reset();
20406
20407 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20408 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20409 IPAddress() /* server_ip */);
20410}
20411
20412TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20413 CreateReportCancelBeforeReadingBody) {
20414 std::string extra_header_string = extra_headers_.ToString();
20415 MockWrite data_writes[] = {
20416 MockWrite("GET / HTTP/1.1\r\n"
20417 "Host: www.example.org\r\n"
20418 "Connection: keep-alive\r\n"),
20419 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20420 };
20421 MockRead data_reads[] = {
20422 MockRead("HTTP/1.0 200 OK\r\n"),
20423 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20424 };
20425
20426 StaticSocketDataProvider data(data_reads, data_writes);
20427 session_deps_.socket_factory->AddSocketDataProvider(&data);
20428
20429 SSLSocketDataProvider ssl(ASYNC, OK);
20430 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20431
20432 TestCompletionCallback callback;
20433 auto session = CreateSession(&session_deps_);
20434 auto trans =
20435 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20436 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20437 EXPECT_THAT(callback.GetResult(rv), IsOk());
20438
20439 const HttpResponseInfo* response = trans->GetResponseInfo();
20440 ASSERT_TRUE(response);
20441
20442 EXPECT_TRUE(response->headers);
20443 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20444
20445 // Cancel before reading the body.
20446 trans.reset();
20447
20448 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20449 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20450}
20451
Lily Chen00196ab62018-12-04 19:52:2920452TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
Lily Chen00196ab62018-12-04 19:52:2920453 RequestPolicy();
20454 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20455 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20456
20457 // Make HTTP request
20458 std::string extra_header_string = extra_headers_.ToString();
20459 MockRead data_reads[] = {
20460 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20461 MockRead("hello world"),
20462 MockRead(SYNCHRONOUS, OK),
20463 };
20464 MockWrite data_writes[] = {
20465 MockWrite("GET / HTTP/1.1\r\n"
20466 "Host: www.example.org\r\n"
20467 "Connection: keep-alive\r\n"),
20468 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20469 };
20470
Lily Chend3930e72019-03-01 19:31:1120471 StaticSocketDataProvider data(data_reads, data_writes);
20472 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920473
Lily Chenfec60d92019-01-24 01:16:4220474 // Insecure url
20475 url_ = "http://www.example.org/";
20476 request_.url = GURL(url_);
20477
Lily Chen00196ab62018-12-04 19:52:2920478 TestCompletionCallback callback;
20479 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220480 auto trans =
20481 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20482 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20483 EXPECT_THAT(callback.GetResult(rv), IsOk());
20484
20485 std::string response_data;
20486 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20487 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920488
20489 // Insecure request does not generate a report
Lily Chen00196ab62018-12-04 19:52:2920490 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20491}
20492
20493TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20494 DontCreateReportHttpError) {
Lily Chen00196ab62018-12-04 19:52:2920495 RequestPolicy();
20496 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20497 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20498
20499 // Make HTTP request that fails
20500 MockRead data_reads[] = {
20501 MockRead("hello world"),
20502 MockRead(SYNCHRONOUS, OK),
20503 };
20504
20505 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20506 session_deps_.socket_factory->AddSocketDataProvider(&data);
20507
Lily Chenfec60d92019-01-24 01:16:4220508 url_ = "http://www.originwithoutpolicy.com:2000/";
20509 request_.url = GURL(url_);
20510
Lily Chen00196ab62018-12-04 19:52:2920511 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20512
Lily Chen00196ab62018-12-04 19:52:2920513 auto trans =
20514 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920515 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220516 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920517 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20518
20519 // Insecure request does not generate a report, regardless of existence of a
20520 // policy for the origin.
Lily Chen00196ab62018-12-04 19:52:2920521 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20522}
20523
Lily Chen90ae93cc2019-02-14 01:15:3920524// Don't report on proxy auth challenges, don't report if connecting through a
20525// proxy.
20526TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20527 HttpRequestInfo request;
20528 request.method = "GET";
20529 request.url = GURL("https://www.example.org/");
20530 request.traffic_annotation =
20531 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20532
20533 // Configure against proxy server "myproxy:70".
20534 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620535 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920536 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20537 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20538
20539 // Since we have proxy, should try to establish tunnel.
20540 MockWrite data_writes1[] = {
20541 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20542 "Host: www.example.org:443\r\n"
20543 "Proxy-Connection: keep-alive\r\n\r\n"),
20544 };
20545
20546 // The proxy responds to the connect with a 407, using a non-persistent
20547 // connection.
20548 MockRead data_reads1[] = {
20549 // No credentials.
20550 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20552 MockRead("Proxy-Connection: close\r\n\r\n"),
20553 };
20554
20555 MockWrite data_writes2[] = {
20556 // After calling trans->RestartWithAuth(), this is the request we should
20557 // be issuing -- the final header line contains the credentials.
20558 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20559 "Host: www.example.org:443\r\n"
20560 "Proxy-Connection: keep-alive\r\n"
20561 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20562
20563 MockWrite("GET / HTTP/1.1\r\n"
20564 "Host: www.example.org\r\n"
20565 "Connection: keep-alive\r\n\r\n"),
20566 };
20567
20568 MockRead data_reads2[] = {
20569 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20570
20571 MockRead("HTTP/1.1 200 OK\r\n"),
20572 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20573 MockRead("Content-Length: 5\r\n\r\n"),
20574 MockRead(SYNCHRONOUS, "hello"),
20575 };
20576
20577 StaticSocketDataProvider data1(data_reads1, data_writes1);
20578 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20579 StaticSocketDataProvider data2(data_reads2, data_writes2);
20580 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20581 SSLSocketDataProvider ssl(ASYNC, OK);
20582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20583
20584 TestCompletionCallback callback1;
20585
20586 auto trans =
20587 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20588
20589 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20590 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20591
20592 const HttpResponseInfo* response = trans->GetResponseInfo();
20593 EXPECT_EQ(407, response->headers->response_code());
20594
20595 std::string response_data;
20596 rv = ReadTransaction(trans.get(), &response_data);
20597 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20598
20599 // No NEL report is generated for the 407.
20600 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20601
20602 TestCompletionCallback callback2;
20603
20604 rv =
20605 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20606 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20607
20608 response = trans->GetResponseInfo();
20609 EXPECT_EQ(200, response->headers->response_code());
20610
20611 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20612 EXPECT_EQ("hello", response_data);
20613
20614 trans.reset();
20615
20616 // No NEL report is generated because we are behind a proxy.
20617 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20618}
20619
Douglas Creageref5eecdc2018-11-09 20:50:3620620TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20621 ReportContainsUploadDepth) {
20622 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220623 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620624 RequestPolicy();
20625 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220626 const NetworkErrorLoggingService::RequestDetails& error =
20627 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620628 EXPECT_EQ(7, error.reporting_upload_depth);
20629}
20630
Lily Chenfec60d92019-01-24 01:16:4220631TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20632 std::string extra_header_string = extra_headers_.ToString();
20633 static const base::TimeDelta kSleepDuration =
20634 base::TimeDelta::FromMilliseconds(10);
20635
20636 std::vector<MockWrite> data_writes = {
20637 MockWrite(ASYNC, 0,
20638 "GET / HTTP/1.1\r\n"
20639 "Host: www.example.org\r\n"
20640 "Connection: keep-alive\r\n"),
20641 MockWrite(ASYNC, 1, extra_header_string.data()),
20642 };
20643
20644 std::vector<MockRead> data_reads = {
20645 // Write one byte of the status line, followed by a pause.
20646 MockRead(ASYNC, 2, "H"),
20647 MockRead(ASYNC, ERR_IO_PENDING, 3),
20648 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20649 MockRead(ASYNC, 5, "hello world"),
20650 MockRead(SYNCHRONOUS, OK, 6),
20651 };
20652
20653 SequencedSocketData data(data_reads, data_writes);
20654 session_deps_.socket_factory->AddSocketDataProvider(&data);
20655
20656 SSLSocketDataProvider ssl(ASYNC, OK);
20657 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20658
20659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20660
20661 auto trans =
20662 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20663
20664 TestCompletionCallback callback;
20665
20666 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20667 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20668
20669 data.RunUntilPaused();
20670 ASSERT_TRUE(data.IsPaused());
20671 FastForwardBy(kSleepDuration);
20672 data.Resume();
20673
20674 EXPECT_THAT(callback.GetResult(rv), IsOk());
20675
20676 std::string response_data;
20677 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20678 EXPECT_EQ("hello world", response_data);
20679
20680 trans.reset();
20681
Douglas Creageref5eecdc2018-11-09 20:50:3620682 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220683
20684 CheckReport(0 /* index */, 200 /* status_code */, OK);
20685
20686 const NetworkErrorLoggingService::RequestDetails& error =
20687 network_error_logging_service()->errors()[0];
20688
20689 // Sanity-check elapsed time in error report
20690 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620691}
Lily Chenfec60d92019-01-24 01:16:4220692
Douglas Creager3cb042052018-11-06 23:08:5220693#endif // BUILDFLAG(ENABLE_REPORTING)
20694
Batalov Vladislava4e97a502019-04-11 15:35:2320695TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20696 HttpRequestInfo request;
20697 request.method = "GET";
20698 request.url = GURL("http://example.org/");
20699
20700 request.load_flags = LOAD_ONLY_FROM_CACHE;
20701
20702 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20703 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20704 TestCompletionCallback callback1;
20705 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
20706
20707 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
20708}
20709
Steven Valdez1c1859172019-04-10 15:33:2820710TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1520711 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820712 HttpRequestInfo request;
20713 request.method = "GET";
20714 request.url = GURL("https://www.example.org/");
20715 request.traffic_annotation =
20716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20717
20718 MockWrite data_writes[] = {
20719 MockWrite("GET / HTTP/1.1\r\n"
20720 "Host: www.example.org\r\n"
20721 "Connection: keep-alive\r\n\r\n"),
20722 };
20723
Steven Valdez1c1859172019-04-10 15:33:2820724 MockRead data_reads[] = {
20725 MockRead("HTTP/1.1 200 OK\r\n"),
20726 MockRead("Content-Length: 1\r\n\r\n"),
20727 MockRead(SYNCHRONOUS, "1"),
20728 };
20729
20730 StaticSocketDataProvider data(data_reads, data_writes);
20731 session_deps_.socket_factory->AddSocketDataProvider(&data);
20732 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520733 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820734 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520735 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820736 session_deps_.enable_early_data = true;
20737 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20738
20739 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20740
20741 TestCompletionCallback callback;
20742 auto trans =
20743 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20744
David Benjaminbae08ba2019-10-18 21:06:1520745 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820746 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20747 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20748
20749 rv = callback.WaitForResult();
20750 EXPECT_THAT(rv, IsOk());
20751
20752 const HttpResponseInfo* response = trans->GetResponseInfo();
20753 ASSERT_TRUE(response);
20754 ASSERT_TRUE(response->headers);
20755 EXPECT_EQ(200, response->headers->response_code());
20756 EXPECT_EQ(1, response->headers->GetContentLength());
20757
20758 // Check that ConfirmHandshake wasn't called.
20759 ASSERT_FALSE(ssl.ConfirmDataConsumed());
20760 ASSERT_TRUE(ssl.WriteBeforeConfirm());
20761
David Benjaminbae08ba2019-10-18 21:06:1520762 // The handshake time should include the time it took to run Connect(), but
20763 // not ConfirmHandshake().
20764 LoadTimingInfo load_timing_info;
20765 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20766 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20767 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20768 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20769 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20770
Steven Valdez1c1859172019-04-10 15:33:2820771 trans.reset();
20772
Matt Menke433de6d2020-03-04 00:24:1120773 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820774}
20775
20776TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520777 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820778 HttpRequestInfo request;
20779 request.method = "POST";
20780 request.url = GURL("https://www.example.org/");
20781 request.traffic_annotation =
20782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20783
20784 MockWrite data_writes[] = {
20785 MockWrite(SYNCHRONOUS,
20786 "POST / HTTP/1.1\r\n"
20787 "Host: www.example.org\r\n"
20788 "Connection: keep-alive\r\n"
20789 "Content-Length: 0\r\n\r\n"),
20790 };
20791
Steven Valdez1c1859172019-04-10 15:33:2820792 MockRead data_reads[] = {
20793 MockRead("HTTP/1.1 200 OK\r\n"),
20794 MockRead("Content-Length: 1\r\n\r\n"),
20795 MockRead(SYNCHRONOUS, "1"),
20796 };
20797
20798 StaticSocketDataProvider data(data_reads, data_writes);
20799 session_deps_.socket_factory->AddSocketDataProvider(&data);
20800 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520801 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820802 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520803 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820804 session_deps_.enable_early_data = true;
20805 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20806
20807 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20808
20809 TestCompletionCallback callback;
20810 auto trans =
20811 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20812
David Benjaminbae08ba2019-10-18 21:06:1520813 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820814 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20815 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20816
20817 rv = callback.WaitForResult();
20818 EXPECT_THAT(rv, IsOk());
20819
20820 const HttpResponseInfo* response = trans->GetResponseInfo();
20821 ASSERT_TRUE(response);
20822 ASSERT_TRUE(response->headers);
20823 EXPECT_EQ(200, response->headers->response_code());
20824 EXPECT_EQ(1, response->headers->GetContentLength());
20825
20826 // Check that the Write didn't get called before ConfirmHandshake completed.
20827 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20828
David Benjaminbae08ba2019-10-18 21:06:1520829 // The handshake time should include the time it took to run Connect(), but
20830 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
20831 // assume the connection did not negotiate 0-RTT or the handshake was already
20832 // confirmed.
20833 LoadTimingInfo load_timing_info;
20834 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20835 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20836 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20837 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20838 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20839
Steven Valdez1c1859172019-04-10 15:33:2820840 trans.reset();
20841
Matt Menke433de6d2020-03-04 00:24:1120842 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820843}
20844
20845TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20846 HttpRequestInfo request;
20847 request.method = "POST";
20848 request.url = GURL("https://www.example.org/");
20849 request.traffic_annotation =
20850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20851
20852 MockWrite data_writes[] = {
20853 MockWrite(ASYNC,
20854 "POST / HTTP/1.1\r\n"
20855 "Host: www.example.org\r\n"
20856 "Connection: keep-alive\r\n"
20857 "Content-Length: 0\r\n\r\n"),
20858 };
20859
Steven Valdez1c1859172019-04-10 15:33:2820860 MockRead data_reads[] = {
20861 MockRead("HTTP/1.1 200 OK\r\n"),
20862 MockRead("Content-Length: 1\r\n\r\n"),
20863 MockRead(SYNCHRONOUS, "1"),
20864 };
20865
20866 StaticSocketDataProvider data(data_reads, data_writes);
20867 session_deps_.socket_factory->AddSocketDataProvider(&data);
20868 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20869 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20870 session_deps_.enable_early_data = true;
20871 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20872
20873 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20874
20875 TestCompletionCallback callback;
20876 auto trans =
20877 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20878
20879 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20881
20882 rv = callback.WaitForResult();
20883 EXPECT_THAT(rv, IsOk());
20884
20885 const HttpResponseInfo* response = trans->GetResponseInfo();
20886 ASSERT_TRUE(response);
20887 ASSERT_TRUE(response->headers);
20888 EXPECT_EQ(200, response->headers->response_code());
20889 EXPECT_EQ(1, response->headers->GetContentLength());
20890
20891 // Check that the Write didn't get called before ConfirmHandshake completed.
20892 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20893
20894 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, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520900 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820901 HttpRequestInfo request;
20902 request.method = "POST";
20903 request.url = GURL("https://www.example.org/");
20904 request.traffic_annotation =
20905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20906
20907 MockWrite data_writes[] = {
20908 MockWrite(SYNCHRONOUS,
20909 "POST / HTTP/1.1\r\n"
20910 "Host: www.example.org\r\n"
20911 "Connection: keep-alive\r\n"
20912 "Content-Length: 0\r\n\r\n"),
20913 };
20914
Steven Valdez1c1859172019-04-10 15:33:2820915 MockRead data_reads[] = {
20916 MockRead("HTTP/1.1 200 OK\r\n"),
20917 MockRead("Content-Length: 1\r\n\r\n"),
20918 MockRead(SYNCHRONOUS, "1"),
20919 };
20920
20921 StaticSocketDataProvider data(data_reads, data_writes);
20922 session_deps_.socket_factory->AddSocketDataProvider(&data);
20923 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520924 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820925 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1520926 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820927 session_deps_.enable_early_data = true;
20928 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20929
20930 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20931
20932 TestCompletionCallback callback;
20933 auto trans =
20934 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20935
David Benjaminbae08ba2019-10-18 21:06:1520936 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820937 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20938 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20939
20940 rv = callback.WaitForResult();
20941 EXPECT_THAT(rv, IsOk());
20942
20943 const HttpResponseInfo* response = trans->GetResponseInfo();
20944 ASSERT_TRUE(response);
20945 ASSERT_TRUE(response->headers);
20946 EXPECT_EQ(200, response->headers->response_code());
20947 EXPECT_EQ(1, response->headers->GetContentLength());
20948
20949 // Check that the Write didn't get called before ConfirmHandshake completed.
20950 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20951
David Benjaminbae08ba2019-10-18 21:06:1520952 // The handshake time should include the time it took to run Connect() and
20953 // ConfirmHandshake().
20954 LoadTimingInfo load_timing_info;
20955 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20956 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20957 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20958 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
20959 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
20960 start_time + 2 * kDelay);
20961
Steven Valdez1c1859172019-04-10 15:33:2820962 trans.reset();
20963
Matt Menke433de6d2020-03-04 00:24:1120964 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2820965}
20966
20967TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20968 HttpRequestInfo request;
20969 request.method = "POST";
20970 request.url = GURL("https://www.example.org/");
20971 request.traffic_annotation =
20972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20973
20974 MockWrite data_writes[] = {
20975 MockWrite(ASYNC,
20976 "POST / HTTP/1.1\r\n"
20977 "Host: www.example.org\r\n"
20978 "Connection: keep-alive\r\n"
20979 "Content-Length: 0\r\n\r\n"),
20980 };
20981
Steven Valdez1c1859172019-04-10 15:33:2820982 MockRead data_reads[] = {
20983 MockRead("HTTP/1.1 200 OK\r\n"),
20984 MockRead("Content-Length: 1\r\n\r\n"),
20985 MockRead(SYNCHRONOUS, "1"),
20986 };
20987
20988 StaticSocketDataProvider data(data_reads, data_writes);
20989 session_deps_.socket_factory->AddSocketDataProvider(&data);
20990 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20991 ssl.confirm = MockConfirm(ASYNC, OK);
20992 session_deps_.enable_early_data = true;
20993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20994
20995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20996
20997 TestCompletionCallback callback;
20998 auto trans =
20999 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21000
21001 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21002 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21003
21004 rv = callback.WaitForResult();
21005 EXPECT_THAT(rv, IsOk());
21006
21007 const HttpResponseInfo* response = trans->GetResponseInfo();
21008 ASSERT_TRUE(response);
21009 ASSERT_TRUE(response->headers);
21010 EXPECT_EQ(200, response->headers->response_code());
21011 EXPECT_EQ(1, response->headers->GetContentLength());
21012
21013 // Check that the Write didn't get called before ConfirmHandshake completed.
21014 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21015
21016 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
David Benjaminfb976932019-05-15 13:39:1521021// 0-RTT rejects are handled at HttpNetworkTransaction.
21022TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
21023 enum class RejectType {
21024 kRead,
21025 kWrite,
21026 kConfirm,
21027 };
21028
21029 for (RejectType type :
21030 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
21031 SCOPED_TRACE(static_cast<int>(type));
21032 for (Error reject_error :
21033 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
21034 SCOPED_TRACE(reject_error);
21035 session_deps_.socket_factory =
21036 std::make_unique<MockClientSocketFactory>();
21037
21038 HttpRequestInfo request;
21039 request.method = type == RejectType::kConfirm ? "POST" : "GET";
21040 request.url = GURL("https://www.example.org/");
21041 request.traffic_annotation =
21042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21043
21044 // The first request fails.
21045 std::vector<MockWrite> data1_writes;
21046 std::vector<MockRead> data1_reads;
21047 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
21048 switch (type) {
21049 case RejectType::kRead:
21050 data1_writes.emplace_back(
21051 "GET / HTTP/1.1\r\n"
21052 "Host: www.example.org\r\n"
21053 "Connection: keep-alive\r\n\r\n");
21054 data1_reads.emplace_back(ASYNC, reject_error);
21055 // Cause ConfirmHandshake to hang (it should not be called).
21056 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21057 break;
21058 case RejectType::kWrite:
21059 data1_writes.emplace_back(ASYNC, reject_error);
21060 // Cause ConfirmHandshake to hang (it should not be called).
21061 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21062 break;
21063 case RejectType::kConfirm:
21064 // The request never gets far enough to read or write.
21065 ssl1.confirm = MockConfirm(ASYNC, reject_error);
21066 break;
21067 }
21068
21069 StaticSocketDataProvider data1(data1_reads, data1_writes);
21070 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21071 session_deps_.enable_early_data = true;
21072 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21073
21074 // The retry succeeds.
21075 //
21076 // TODO(https://crbug.com/950705): If |reject_error| is
21077 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
21078 MockWrite data2_writes[] = {
21079 request.method == "POST"
21080 ? MockWrite("POST / HTTP/1.1\r\n"
21081 "Host: www.example.org\r\n"
21082 "Connection: keep-alive\r\n"
21083 "Content-Length: 0\r\n\r\n")
21084 : MockWrite("GET / HTTP/1.1\r\n"
21085 "Host: www.example.org\r\n"
21086 "Connection: keep-alive\r\n\r\n"),
21087 };
21088
21089 MockRead data2_reads[] = {
21090 MockRead("HTTP/1.1 200 OK\r\n"),
21091 MockRead("Content-Length: 1\r\n\r\n"),
21092 MockRead(SYNCHRONOUS, "1"),
21093 };
21094
21095 StaticSocketDataProvider data2(data2_reads, data2_writes);
21096 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21097 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21098 ssl2.confirm = MockConfirm(ASYNC, OK);
21099 session_deps_.enable_early_data = true;
21100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21101
21102 std::unique_ptr<HttpNetworkSession> session(
21103 CreateSession(&session_deps_));
21104
21105 TestCompletionCallback callback;
21106 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21107 session.get());
21108
21109 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21110 NetLogWithSource())),
21111 IsOk());
21112
21113 const HttpResponseInfo* response = trans->GetResponseInfo();
21114 ASSERT_TRUE(response);
21115 ASSERT_TRUE(response->headers);
21116 EXPECT_EQ(200, response->headers->response_code());
21117 EXPECT_EQ(1, response->headers->GetContentLength());
21118 }
21119 }
21120}
21121
Steven Valdez1c1859172019-04-10 15:33:2821122TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21123 HttpRequestInfo request;
21124 request.method = "POST";
21125 request.url = GURL("https://www.example.org/");
21126 request.traffic_annotation =
21127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21128
21129 MockWrite data_writes[] = {
21130 MockWrite("POST / HTTP/1.1\r\n"
21131 "Host: www.example.org\r\n"
21132 "Connection: keep-alive\r\n"
21133 "Content-Length: 0\r\n\r\n"),
21134 };
21135
Steven Valdez1c1859172019-04-10 15:33:2821136 MockRead data_reads[] = {
21137 MockRead("HTTP/1.1 200 OK\r\n"),
21138 MockRead("Content-Length: 1\r\n\r\n"),
21139 MockRead(SYNCHRONOUS, "1"),
21140 };
21141
21142 StaticSocketDataProvider data(data_reads, data_writes);
21143 session_deps_.socket_factory->AddSocketDataProvider(&data);
21144 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21145 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21146 session_deps_.enable_early_data = true;
21147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21148
21149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21150
21151 TestCompletionCallback callback;
21152 auto trans =
21153 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21154
21155 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21157
21158 rv = callback.WaitForResult();
21159 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21160
21161 // Check that the Write didn't get called before ConfirmHandshake completed.
21162 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21163
21164 trans.reset();
21165
Matt Menke433de6d2020-03-04 00:24:1121166 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821167}
21168
21169TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21170 HttpRequestInfo request;
21171 request.method = "POST";
21172 request.url = GURL("https://www.example.org/");
21173 request.traffic_annotation =
21174 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21175
21176 MockWrite data_writes[] = {
21177 MockWrite("POST / HTTP/1.1\r\n"
21178 "Host: www.example.org\r\n"
21179 "Connection: keep-alive\r\n"
21180 "Content-Length: 0\r\n\r\n"),
21181 };
21182
Steven Valdez1c1859172019-04-10 15:33:2821183 MockRead data_reads[] = {
21184 MockRead("HTTP/1.1 200 OK\r\n"),
21185 MockRead("Content-Length: 1\r\n\r\n"),
21186 MockRead(SYNCHRONOUS, "1"),
21187 };
21188
21189 StaticSocketDataProvider data(data_reads, data_writes);
21190 session_deps_.socket_factory->AddSocketDataProvider(&data);
21191 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21192 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21193 session_deps_.enable_early_data = true;
21194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21195
21196 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21197
21198 TestCompletionCallback callback;
21199 auto trans =
21200 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21201
21202 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21203 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21204
21205 rv = callback.WaitForResult();
21206 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21207
21208 // Check that the Write didn't get called before ConfirmHandshake completed.
21209 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21210
21211 trans.reset();
21212
Matt Menke433de6d2020-03-04 00:24:1121213 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821214}
21215
David Benjamin2eb827f2019-04-29 18:31:0421216// Test the proxy and origin server each requesting both TLS client certificates
21217// and HTTP auth. This is a regression test for https://crbug.com/946406.
21218TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21219 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621220 session_deps_.proxy_resolution_service =
21221 ConfiguredProxyResolutionService::CreateFixed(
21222 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421223
21224 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21225 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21226
21227 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21228 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21229 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21230 ASSERT_TRUE(identity_proxy);
21231
21232 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21233 cert_request_info_origin->host_and_port =
21234 HostPortPair("www.example.org", 443);
21235
21236 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21237 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21238 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21239 ASSERT_TRUE(identity_origin);
21240
21241 HttpRequestInfo request;
21242 request.method = "GET";
21243 request.url = GURL("https://www.example.org/");
21244 request.traffic_annotation =
21245 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21246
David Benjamin7ebab032019-04-30 21:51:3021247 // First, the client connects to the proxy, which requests a client
21248 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421249 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21250 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21251 ssl_proxy1.expected_send_client_cert = false;
21252 StaticSocketDataProvider data1;
21253 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021254 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421255
David Benjamin7ebab032019-04-30 21:51:3021256 // The client responds with a certificate on a new connection. The handshake
21257 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421258 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21259 ssl_proxy2.expected_send_client_cert = true;
21260 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021261 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421262 std::vector<MockWrite> mock_writes2;
21263 std::vector<MockRead> mock_reads2;
21264 mock_writes2.emplace_back(
21265 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21266 "Host: www.example.org:443\r\n"
21267 "Proxy-Connection: keep-alive\r\n\r\n");
21268 mock_reads2.emplace_back(
21269 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21270 "Content-Length: 0\r\n"
21271 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021272 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421273 mock_writes2.emplace_back(
21274 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21275 "Host: www.example.org:443\r\n"
21276 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021277 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421278 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21279 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21280 // The origin requests client certificates.
21281 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21282 ssl_origin2.cert_request_info = cert_request_info_origin.get();
21283 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21284 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21286 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421287
David Benjamin7ebab032019-04-30 21:51:3021288 // The client responds to the origin client certificate request on a new
21289 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421290 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21291 ssl_proxy3.expected_send_client_cert = true;
21292 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21293 std::vector<MockWrite> mock_writes3;
21294 std::vector<MockRead> mock_reads3;
21295 mock_writes3.emplace_back(
21296 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21297 "Host: www.example.org:443\r\n"
21298 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021299 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421300 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21301 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21302 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21303 ssl_origin3.expected_send_client_cert = true;
21304 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021305 // The client sends the origin HTTP request, which results in another HTTP
21306 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421307 mock_writes3.emplace_back(
21308 "GET / HTTP/1.1\r\n"
21309 "Host: www.example.org\r\n"
21310 "Connection: keep-alive\r\n\r\n");
21311 mock_reads3.emplace_back(
21312 "HTTP/1.1 401 Unauthorized\r\n"
21313 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21314 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021315 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421316 mock_writes3.emplace_back(
21317 "GET / HTTP/1.1\r\n"
21318 "Host: www.example.org\r\n"
21319 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021320 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421321 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21322 mock_reads3.emplace_back(
21323 "HTTP/1.1 200 OK\r\n"
21324 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121325 // The client makes another request. This should reuse the socket with all
21326 // credentials cached.
21327 mock_writes3.emplace_back(
21328 "GET / HTTP/1.1\r\n"
21329 "Host: www.example.org\r\n"
21330 "Connection: keep-alive\r\n"
21331 // Authenticate as user:pass.
21332 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21333 mock_reads3.emplace_back(
21334 "HTTP/1.1 200 OK\r\n"
21335 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421336 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21337 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021338 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21339 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421340
21341 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21342
21343 // Start the request.
21344 TestCompletionCallback callback;
21345 auto trans =
21346 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21347 int rv = callback.GetResult(
21348 trans->Start(&request, callback.callback(), NetLogWithSource()));
21349
21350 // Handle the proxy client certificate challenge.
21351 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21352 SSLCertRequestInfo* cert_request_info =
21353 trans->GetResponseInfo()->cert_request_info.get();
21354 ASSERT_TRUE(cert_request_info);
21355 EXPECT_TRUE(cert_request_info->is_proxy);
21356 EXPECT_EQ(cert_request_info->host_and_port,
21357 cert_request_info_proxy->host_and_port);
21358 rv = callback.GetResult(trans->RestartWithCertificate(
21359 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21360 callback.callback()));
21361
21362 // Handle the proxy HTTP auth challenge.
21363 ASSERT_THAT(rv, IsOk());
21364 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21365 EXPECT_TRUE(
21366 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21367 rv = callback.GetResult(trans->RestartWithAuth(
21368 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21369 callback.callback()));
21370
21371 // Handle the origin client certificate challenge.
21372 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21373 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21374 ASSERT_TRUE(cert_request_info);
21375 EXPECT_FALSE(cert_request_info->is_proxy);
21376 EXPECT_EQ(cert_request_info->host_and_port,
21377 cert_request_info_origin->host_and_port);
21378 rv = callback.GetResult(trans->RestartWithCertificate(
21379 identity_origin->certificate(), identity_origin->ssl_private_key(),
21380 callback.callback()));
21381
21382 // Handle the origin HTTP auth challenge.
21383 ASSERT_THAT(rv, IsOk());
21384 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21385 EXPECT_TRUE(
21386 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21387 rv = callback.GetResult(trans->RestartWithAuth(
21388 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21389 callback.callback()));
21390
21391 // The request completes.
21392 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021393 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121394
21395 // Make a second request. This time all credentials are cached.
21396 trans =
21397 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21398 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21399 NetLogWithSource())),
21400 IsOk());
21401 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421402}
21403
21404// Test the proxy and origin server each requesting both TLS client certificates
21405// and HTTP auth and each HTTP auth closing the connection. This is a regression
21406// test for https://crbug.com/946406.
21407TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21408 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621409 session_deps_.proxy_resolution_service =
21410 ConfiguredProxyResolutionService::CreateFixed(
21411 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421412
21413 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21414 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21415
21416 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21417 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21418 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21419 ASSERT_TRUE(identity_proxy);
21420
21421 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21422 cert_request_info_origin->host_and_port =
21423 HostPortPair("www.example.org", 443);
21424
21425 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21426 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21427 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21428 ASSERT_TRUE(identity_origin);
21429
21430 HttpRequestInfo request;
21431 request.method = "GET";
21432 request.url = GURL("https://www.example.org/");
21433 request.traffic_annotation =
21434 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21435
David Benjamin7ebab032019-04-30 21:51:3021436 // First, the client connects to the proxy, which requests a client
21437 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421438 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21439 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21440 ssl_proxy1.expected_send_client_cert = false;
21441 StaticSocketDataProvider data1;
21442 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021443 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421444
David Benjamin7ebab032019-04-30 21:51:3021445 // The client responds with a certificate on a new connection. The handshake
21446 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421447 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21448 ssl_proxy2.expected_send_client_cert = true;
21449 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021450 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421451 std::vector<MockWrite> mock_writes2;
21452 std::vector<MockRead> mock_reads2;
21453 mock_writes2.emplace_back(
21454 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21455 "Host: www.example.org:443\r\n"
21456 "Proxy-Connection: keep-alive\r\n\r\n");
21457 mock_reads2.emplace_back(
21458 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21459 "Content-Length: 0\r\n"
21460 "Proxy-Connection: close\r\n"
21461 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21462 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21463 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421465
David Benjamin7ebab032019-04-30 21:51:3021466 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421467 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21468 ssl_proxy3.expected_send_client_cert = true;
21469 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21470 std::vector<MockWrite> mock_writes3;
21471 std::vector<MockRead> mock_reads3;
21472 mock_writes3.emplace_back(
21473 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21474 "Host: www.example.org:443\r\n"
21475 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021476 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421477 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21478 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21479 // The origin requests client certificates.
21480 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21481 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21482 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21483 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21485 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421486
David Benjamin7ebab032019-04-30 21:51:3021487 // The client responds to the origin client certificate request on a new
21488 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421489 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21490 ssl_proxy4.expected_send_client_cert = true;
21491 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21492 std::vector<MockWrite> mock_writes4;
21493 std::vector<MockRead> mock_reads4;
21494 mock_writes4.emplace_back(
21495 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21496 "Host: www.example.org:443\r\n"
21497 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021498 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421499 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21500 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21501 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21502 ssl_origin4.expected_send_client_cert = true;
21503 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021504 // The client sends the origin HTTP request, which results in another HTTP
21505 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421506 mock_writes4.emplace_back(
21507 "GET / HTTP/1.1\r\n"
21508 "Host: www.example.org\r\n"
21509 "Connection: keep-alive\r\n\r\n");
21510 mock_reads4.emplace_back(
21511 "HTTP/1.1 401 Unauthorized\r\n"
21512 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21513 "Connection: close\r\n"
21514 "Content-Length: 0\r\n\r\n");
21515 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21516 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21518 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421519
David Benjamin7ebab032019-04-30 21:51:3021520 // The client retries with credentials on a new connection, and the request
21521 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421522 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21523 ssl_proxy5.expected_send_client_cert = true;
21524 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21525 std::vector<MockWrite> mock_writes5;
21526 std::vector<MockRead> mock_reads5;
21527 mock_writes5.emplace_back(
21528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21529 "Host: www.example.org:443\r\n"
21530 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021531 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421532 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21533 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21534 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21535 ssl_origin5.expected_send_client_cert = true;
21536 ssl_origin5.expected_client_cert = identity_origin->certificate();
21537 mock_writes5.emplace_back(
21538 "GET / HTTP/1.1\r\n"
21539 "Host: www.example.org\r\n"
21540 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021541 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421542 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21543 mock_reads5.emplace_back(
21544 "HTTP/1.1 200 OK\r\n"
21545 "Connection: close\r\n"
21546 "Content-Length: 0\r\n\r\n");
21547 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21548 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021549 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421551
David Benjaminbac8dff2019-08-07 01:30:4121552 // The client makes a second request. This needs yet another connection, but
21553 // all credentials are cached.
21554 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21555 ssl_proxy6.expected_send_client_cert = true;
21556 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21557 std::vector<MockWrite> mock_writes6;
21558 std::vector<MockRead> mock_reads6;
21559 mock_writes6.emplace_back(
21560 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21561 "Host: www.example.org:443\r\n"
21562 "Proxy-Connection: keep-alive\r\n"
21563 // Authenticate as proxyuser:proxypass.
21564 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21565 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21566 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21567 ssl_origin6.expected_send_client_cert = true;
21568 ssl_origin6.expected_client_cert = identity_origin->certificate();
21569 mock_writes6.emplace_back(
21570 "GET / HTTP/1.1\r\n"
21571 "Host: www.example.org\r\n"
21572 "Connection: keep-alive\r\n"
21573 // Authenticate as user:pass.
21574 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21575 mock_reads6.emplace_back(
21576 "HTTP/1.1 200 OK\r\n"
21577 "Connection: close\r\n"
21578 "Content-Length: 0\r\n\r\n");
21579 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21580 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21583
David Benjamin2eb827f2019-04-29 18:31:0421584 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21585
21586 // Start the request.
21587 TestCompletionCallback callback;
21588 auto trans =
21589 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21590 int rv = callback.GetResult(
21591 trans->Start(&request, callback.callback(), NetLogWithSource()));
21592
21593 // Handle the proxy client certificate challenge.
21594 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21595 SSLCertRequestInfo* cert_request_info =
21596 trans->GetResponseInfo()->cert_request_info.get();
21597 ASSERT_TRUE(cert_request_info);
21598 EXPECT_TRUE(cert_request_info->is_proxy);
21599 EXPECT_EQ(cert_request_info->host_and_port,
21600 cert_request_info_proxy->host_and_port);
21601 rv = callback.GetResult(trans->RestartWithCertificate(
21602 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21603 callback.callback()));
21604
21605 // Handle the proxy HTTP auth challenge.
21606 ASSERT_THAT(rv, IsOk());
21607 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21608 EXPECT_TRUE(
21609 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21610 rv = callback.GetResult(trans->RestartWithAuth(
21611 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21612 callback.callback()));
21613
21614 // Handle the origin client certificate challenge.
21615 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21616 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21617 ASSERT_TRUE(cert_request_info);
21618 EXPECT_FALSE(cert_request_info->is_proxy);
21619 EXPECT_EQ(cert_request_info->host_and_port,
21620 cert_request_info_origin->host_and_port);
21621 rv = callback.GetResult(trans->RestartWithCertificate(
21622 identity_origin->certificate(), identity_origin->ssl_private_key(),
21623 callback.callback()));
21624
21625 // Handle the origin HTTP auth challenge.
21626 ASSERT_THAT(rv, IsOk());
21627 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21628 EXPECT_TRUE(
21629 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21630 rv = callback.GetResult(trans->RestartWithAuth(
21631 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21632 callback.callback()));
21633
21634 // The request completes.
21635 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021636 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121637
21638 // Make a second request. This time all credentials are cached.
21639 trans =
21640 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21641 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21642 NetLogWithSource())),
21643 IsOk());
21644 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021645}
21646
21647// Test the proxy requesting HTTP auth and the server requesting TLS client
21648// certificates. This is a regression test for https://crbug.com/946406.
21649TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21650 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621651 session_deps_.proxy_resolution_service =
21652 ConfiguredProxyResolutionService::CreateFixed(
21653 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin7ebab032019-04-30 21:51:3021654
21655 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21656 cert_request_info_origin->host_and_port =
21657 HostPortPair("www.example.org", 443);
21658
21659 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21660 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21661 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21662 ASSERT_TRUE(identity_origin);
21663
21664 HttpRequestInfo request;
21665 request.method = "GET";
21666 request.url = GURL("https://www.example.org/");
21667 request.traffic_annotation =
21668 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21669
21670 // The client connects to the proxy. The handshake succeeds.
21671 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21672 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21673 std::vector<MockWrite> mock_writes1;
21674 std::vector<MockRead> mock_reads1;
21675 mock_writes1.emplace_back(
21676 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21677 "Host: www.example.org:443\r\n"
21678 "Proxy-Connection: keep-alive\r\n\r\n");
21679 mock_reads1.emplace_back(
21680 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21681 "Content-Length: 0\r\n"
21682 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21683 // The client retries with credentials, and the request finally succeeds.
21684 mock_writes1.emplace_back(
21685 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21686 "Host: www.example.org:443\r\n"
21687 "Proxy-Connection: keep-alive\r\n"
21688 // Authenticate as proxyuser:proxypass.
21689 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21690 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21691 // The origin requests client certificates.
21692 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21693 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21694 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21695 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21696 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21698
21699 // The client responds to the origin client certificate request on a new
21700 // connection.
21701 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21702 std::vector<MockWrite> mock_writes2;
21703 std::vector<MockRead> mock_reads2;
21704 mock_writes2.emplace_back(
21705 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21706 "Host: www.example.org:443\r\n"
21707 "Proxy-Connection: keep-alive\r\n"
21708 // Authenticate as proxyuser:proxypass.
21709 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21710 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21711 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
21712 ssl_origin2.expected_send_client_cert = true;
21713 ssl_origin2.expected_client_cert = identity_origin->certificate();
21714 // The client sends the origin HTTP request, which succeeds.
21715 mock_writes2.emplace_back(
21716 "GET / HTTP/1.1\r\n"
21717 "Host: www.example.org\r\n"
21718 "Connection: keep-alive\r\n\r\n");
21719 mock_reads2.emplace_back(
21720 "HTTP/1.1 200 OK\r\n"
21721 "Content-Length: 0\r\n\r\n");
21722 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21723 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21724 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21725 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
21726
21727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21728
21729 // Start the request.
21730 TestCompletionCallback callback;
21731 auto trans =
21732 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21733 int rv = callback.GetResult(
21734 trans->Start(&request, callback.callback(), NetLogWithSource()));
21735
21736 // Handle the proxy HTTP auth challenge.
21737 ASSERT_THAT(rv, IsOk());
21738 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21739 EXPECT_TRUE(
21740 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21741 rv = callback.GetResult(trans->RestartWithAuth(
21742 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21743 callback.callback()));
21744
21745 // Handle the origin client certificate challenge.
21746 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21747 SSLCertRequestInfo* cert_request_info =
21748 trans->GetResponseInfo()->cert_request_info.get();
21749 ASSERT_TRUE(cert_request_info);
21750 EXPECT_FALSE(cert_request_info->is_proxy);
21751 EXPECT_EQ(cert_request_info->host_and_port,
21752 cert_request_info_origin->host_and_port);
21753 rv = callback.GetResult(trans->RestartWithCertificate(
21754 identity_origin->certificate(), identity_origin->ssl_private_key(),
21755 callback.callback()));
21756
21757 // The request completes.
21758 ASSERT_THAT(rv, IsOk());
21759 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421760}
21761
David Benjamin6e673a82019-04-30 22:52:5821762// Test that socket reuse works with client certificates.
21763TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
21764 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21765 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
21766
21767 std::unique_ptr<FakeClientCertIdentity> identity =
21768 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21769 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21770 ASSERT_TRUE(identity);
21771
21772 HttpRequestInfo request1;
21773 request1.method = "GET";
21774 request1.url = GURL("https://www.example.org/a");
21775 request1.traffic_annotation =
21776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21777
21778 HttpRequestInfo request2;
21779 request2.method = "GET";
21780 request2.url = GURL("https://www.example.org/b");
21781 request2.traffic_annotation =
21782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21783
21784 // The first connection results in a client certificate request.
21785 StaticSocketDataProvider data1;
21786 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21787 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21788 ssl1.cert_request_info = cert_request_info.get();
21789 ssl1.expected_send_client_cert = false;
21790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21791
21792 // The second connection succeeds and is usable for both requests.
21793 MockWrite mock_writes[] = {
21794 MockWrite("GET /a HTTP/1.1\r\n"
21795 "Host: www.example.org\r\n"
21796 "Connection: keep-alive\r\n\r\n"),
21797 MockWrite("GET /b HTTP/1.1\r\n"
21798 "Host: www.example.org\r\n"
21799 "Connection: keep-alive\r\n\r\n"),
21800 };
21801 MockRead mock_reads[] = {
21802 MockRead("HTTP/1.1 200 OK\r\n"
21803 "Content-Length: 0\r\n\r\n"),
21804 MockRead("HTTP/1.1 200 OK\r\n"
21805 "Content-Length: 0\r\n\r\n"),
21806 };
21807 StaticSocketDataProvider data2(mock_reads, mock_writes);
21808 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21809 SSLSocketDataProvider ssl2(ASYNC, OK);
21810 ssl2.expected_send_client_cert = true;
21811 ssl2.expected_client_cert = identity->certificate();
21812 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21813
21814 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21815
21816 // Start the first request. It succeeds after providing client certificates.
21817 TestCompletionCallback callback;
21818 auto trans =
21819 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21820 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
21821 NetLogWithSource())),
21822 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21823
21824 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
21825 ASSERT_TRUE(info);
21826 EXPECT_FALSE(info->is_proxy);
21827 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21828
21829 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21830 identity->certificate(), identity->ssl_private_key(),
21831 callback.callback())),
21832 IsOk());
21833 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21834
21835 // Make the second request. It completes without requesting client
21836 // certificates.
21837 trans =
21838 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21839 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21840 NetLogWithSource())),
21841 IsOk());
21842 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21843}
21844
Matt Menke166443c2019-05-24 18:45:5921845// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21846// sequence with two different NetworkIsolationKeys, the first and last have the
21847// same key, the second a different one. Checks that the requests are
21848// partitioned across sockets as expected.
21849TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721850 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21851 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21852 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21853 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921854
21855 for (bool partition_connections : {false, true}) {
21856 SCOPED_TRACE(partition_connections);
21857
21858 base::test::ScopedFeatureList feature_list;
21859 if (partition_connections) {
21860 feature_list.InitAndEnableFeature(
21861 features::kPartitionConnectionsByNetworkIsolationKey);
21862 } else {
21863 feature_list.InitAndDisableFeature(
21864 features::kPartitionConnectionsByNetworkIsolationKey);
21865 }
21866
21867 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21868
21869 // Reads and writes for the unpartitioned case, where only one socket is
21870 // used.
21871
21872 const MockWrite kUnpartitionedWrites[] = {
21873 MockWrite("GET /1 HTTP/1.1\r\n"
21874 "Host: foo.test\r\n"
21875 "Connection: keep-alive\r\n\r\n"),
21876 MockWrite("GET /2 HTTP/1.1\r\n"
21877 "Host: foo.test\r\n"
21878 "Connection: keep-alive\r\n\r\n"),
21879 MockWrite("GET /3 HTTP/1.1\r\n"
21880 "Host: foo.test\r\n"
21881 "Connection: keep-alive\r\n\r\n"),
21882 };
21883
21884 const MockRead kUnpartitionedReads[] = {
21885 MockRead("HTTP/1.1 200 OK\r\n"
21886 "Connection: keep-alive\r\n"
21887 "Content-Length: 1\r\n\r\n"
21888 "1"),
21889 MockRead("HTTP/1.1 200 OK\r\n"
21890 "Connection: keep-alive\r\n"
21891 "Content-Length: 1\r\n\r\n"
21892 "2"),
21893 MockRead("HTTP/1.1 200 OK\r\n"
21894 "Connection: keep-alive\r\n"
21895 "Content-Length: 1\r\n\r\n"
21896 "3"),
21897 };
21898
21899 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21900 kUnpartitionedWrites);
21901
21902 // Reads and writes for the partitioned case, where two sockets are used.
21903
21904 const MockWrite kPartitionedWrites1[] = {
21905 MockWrite("GET /1 HTTP/1.1\r\n"
21906 "Host: foo.test\r\n"
21907 "Connection: keep-alive\r\n\r\n"),
21908 MockWrite("GET /3 HTTP/1.1\r\n"
21909 "Host: foo.test\r\n"
21910 "Connection: keep-alive\r\n\r\n"),
21911 };
21912
21913 const MockRead kPartitionedReads1[] = {
21914 MockRead("HTTP/1.1 200 OK\r\n"
21915 "Connection: keep-alive\r\n"
21916 "Content-Length: 1\r\n\r\n"
21917 "1"),
21918 MockRead("HTTP/1.1 200 OK\r\n"
21919 "Connection: keep-alive\r\n"
21920 "Content-Length: 1\r\n\r\n"
21921 "3"),
21922 };
21923
21924 const MockWrite kPartitionedWrites2[] = {
21925 MockWrite("GET /2 HTTP/1.1\r\n"
21926 "Host: foo.test\r\n"
21927 "Connection: keep-alive\r\n\r\n"),
21928 };
21929
21930 const MockRead kPartitionedReads2[] = {
21931 MockRead("HTTP/1.1 200 OK\r\n"
21932 "Connection: keep-alive\r\n"
21933 "Content-Length: 1\r\n\r\n"
21934 "2"),
21935 };
21936
21937 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21938 kPartitionedWrites1);
21939 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21940 kPartitionedWrites2);
21941
21942 if (partition_connections) {
21943 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21944 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21945 } else {
21946 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21947 }
21948
21949 TestCompletionCallback callback;
21950 HttpRequestInfo request1;
21951 request1.method = "GET";
21952 request1.url = GURL("http://foo.test/1");
21953 request1.traffic_annotation =
21954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21955 request1.network_isolation_key = network_isolation_key1;
21956 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21957 session.get());
21958 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21959 EXPECT_THAT(callback.GetResult(rv), IsOk());
21960 std::string response_data1;
21961 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21962 EXPECT_EQ("1", response_data1);
21963 trans1.reset();
21964
21965 HttpRequestInfo request2;
21966 request2.method = "GET";
21967 request2.url = GURL("http://foo.test/2");
21968 request2.traffic_annotation =
21969 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21970 request2.network_isolation_key = network_isolation_key2;
21971 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21972 session.get());
21973 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21974 EXPECT_THAT(callback.GetResult(rv), IsOk());
21975 std::string response_data2;
21976 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21977 EXPECT_EQ("2", response_data2);
21978 trans2.reset();
21979
21980 HttpRequestInfo request3;
21981 request3.method = "GET";
21982 request3.url = GURL("http://foo.test/3");
21983 request3.traffic_annotation =
21984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21985 request3.network_isolation_key = network_isolation_key1;
21986 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21987 session.get());
21988 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21989 EXPECT_THAT(callback.GetResult(rv), IsOk());
21990 std::string response_data3;
21991 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21992 EXPECT_EQ("3", response_data3);
21993 trans3.reset();
21994 }
21995}
21996
Matt Menkeae58eeb2019-05-24 21:09:5021997TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721998 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21999 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22000 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
22001 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5022002
22003 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
22004 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
22005 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
22006 // the same way as the HTTP over H2 proxy case.
22007 for (bool use_proxy : {false, true}) {
22008 SCOPED_TRACE(use_proxy);
22009 if (use_proxy) {
22010 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622011 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkeae58eeb2019-05-24 21:09:5022012 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
22013 } else {
22014 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622015 ConfiguredProxyResolutionService::CreateDirect();
Matt Menkeae58eeb2019-05-24 21:09:5022016 }
22017 const char* url1 = nullptr;
22018 const char* url2 = nullptr;
22019 const char* url3 = nullptr;
22020 if (use_proxy) {
22021 url1 = "http://foo.test/1";
22022 url2 = "http://foo.test/2";
22023 url3 = "http://foo.test/3";
22024 } else {
22025 url1 = "https://foo.test/1";
22026 url2 = "https://foo.test/2";
22027 url3 = "https://foo.test/3";
22028 }
22029
22030 for (bool partition_connections : {false, true}) {
22031 SCOPED_TRACE(partition_connections);
22032
22033 base::test::ScopedFeatureList feature_list;
22034 if (partition_connections) {
22035 feature_list.InitAndEnableFeature(
22036 features::kPartitionConnectionsByNetworkIsolationKey);
22037 } else {
22038 feature_list.InitAndDisableFeature(
22039 features::kPartitionConnectionsByNetworkIsolationKey);
22040 }
22041
22042 std::unique_ptr<HttpNetworkSession> session(
22043 CreateSession(&session_deps_));
22044
22045 // Reads and writes for the unpartitioned case, where only one socket is
22046 // used.
22047
22048 SpdyTestUtil spdy_util;
22049 spdy::SpdySerializedFrame unpartitioned_req1(
22050 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
22051 spdy::SpdySerializedFrame unpartitioned_response1(
22052 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
22053 spdy::SpdySerializedFrame unpartitioned_body1(
22054 spdy_util.ConstructSpdyDataFrame(1, "1", true));
22055 spdy_util.UpdateWithStreamDestruction(1);
22056
22057 spdy::SpdySerializedFrame unpartitioned_req2(
22058 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
22059 spdy::SpdySerializedFrame unpartitioned_response2(
22060 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
22061 spdy::SpdySerializedFrame unpartitioned_body2(
22062 spdy_util.ConstructSpdyDataFrame(3, "2", true));
22063 spdy_util.UpdateWithStreamDestruction(3);
22064
22065 spdy::SpdySerializedFrame unpartitioned_req3(
22066 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
22067 spdy::SpdySerializedFrame unpartitioned_response3(
22068 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
22069 spdy::SpdySerializedFrame unpartitioned_body3(
22070 spdy_util.ConstructSpdyDataFrame(5, "3", true));
22071
22072 const MockWrite kUnpartitionedWrites[] = {
22073 CreateMockWrite(unpartitioned_req1, 0),
22074 CreateMockWrite(unpartitioned_req2, 3),
22075 CreateMockWrite(unpartitioned_req3, 6),
22076 };
22077
22078 const MockRead kUnpartitionedReads[] = {
22079 CreateMockRead(unpartitioned_response1, 1),
22080 CreateMockRead(unpartitioned_body1, 2),
22081 CreateMockRead(unpartitioned_response2, 4),
22082 CreateMockRead(unpartitioned_body2, 5),
22083 CreateMockRead(unpartitioned_response3, 7),
22084 CreateMockRead(unpartitioned_body3, 8),
22085 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
22086 };
22087
22088 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
22089 kUnpartitionedWrites);
22090
22091 // Reads and writes for the partitioned case, where two sockets are used.
22092
22093 SpdyTestUtil spdy_util2;
22094 spdy::SpdySerializedFrame partitioned_req1(
22095 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22096 spdy::SpdySerializedFrame partitioned_response1(
22097 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22098 spdy::SpdySerializedFrame partitioned_body1(
22099 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22100 spdy_util2.UpdateWithStreamDestruction(1);
22101
22102 spdy::SpdySerializedFrame partitioned_req3(
22103 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22104 spdy::SpdySerializedFrame partitioned_response3(
22105 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22106 spdy::SpdySerializedFrame partitioned_body3(
22107 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22108
22109 const MockWrite kPartitionedWrites1[] = {
22110 CreateMockWrite(partitioned_req1, 0),
22111 CreateMockWrite(partitioned_req3, 3),
22112 };
22113
22114 const MockRead kPartitionedReads1[] = {
22115 CreateMockRead(partitioned_response1, 1),
22116 CreateMockRead(partitioned_body1, 2),
22117 CreateMockRead(partitioned_response3, 4),
22118 CreateMockRead(partitioned_body3, 5),
22119 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22120 };
22121
22122 SpdyTestUtil spdy_util3;
22123 spdy::SpdySerializedFrame partitioned_req2(
22124 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22125 spdy::SpdySerializedFrame partitioned_response2(
22126 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22127 spdy::SpdySerializedFrame partitioned_body2(
22128 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22129
22130 const MockWrite kPartitionedWrites2[] = {
22131 CreateMockWrite(partitioned_req2, 0),
22132 };
22133
22134 const MockRead kPartitionedReads2[] = {
22135 CreateMockRead(partitioned_response2, 1),
22136 CreateMockRead(partitioned_body2, 2),
22137 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22138 };
22139
22140 SequencedSocketData partitioned_data1(kPartitionedReads1,
22141 kPartitionedWrites1);
22142 SequencedSocketData partitioned_data2(kPartitionedReads2,
22143 kPartitionedWrites2);
22144
22145 // No need to segment SSLDataProviders by whether or not partitioning is
22146 // enabled.
22147 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22148 ssl_data1.next_proto = kProtoHTTP2;
22149 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22150 ssl_data2.next_proto = kProtoHTTP2;
22151
22152 if (partition_connections) {
22153 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22155 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22157 } else {
22158 session_deps_.socket_factory->AddSocketDataProvider(
22159 &unpartitioned_data);
22160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22161 }
22162
22163 TestCompletionCallback callback;
22164 HttpRequestInfo request1;
22165 request1.method = "GET";
22166 request1.url = GURL(url1);
22167 request1.traffic_annotation =
22168 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22169 request1.network_isolation_key = network_isolation_key1;
22170 auto trans1 =
22171 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22172 int rv =
22173 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22174 EXPECT_THAT(callback.GetResult(rv), IsOk());
22175 std::string response_data1;
22176 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22177 EXPECT_EQ("1", response_data1);
22178 trans1.reset();
22179
22180 HttpRequestInfo request2;
22181 request2.method = "GET";
22182 request2.url = GURL(url2);
22183 request2.traffic_annotation =
22184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22185 request2.network_isolation_key = network_isolation_key2;
22186 auto trans2 =
22187 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22188 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22189 EXPECT_THAT(callback.GetResult(rv), IsOk());
22190 std::string response_data2;
22191 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22192 EXPECT_EQ("2", response_data2);
22193 trans2.reset();
22194
22195 HttpRequestInfo request3;
22196 request3.method = "GET";
22197 request3.url = GURL(url3);
22198 request3.traffic_annotation =
22199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22200 request3.network_isolation_key = network_isolation_key1;
22201 auto trans3 =
22202 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22203 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22204 EXPECT_THAT(callback.GetResult(rv), IsOk());
22205 std::string response_data3;
22206 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22207 EXPECT_EQ("3", response_data3);
22208 trans3.reset();
22209 }
22210 }
22211}
22212
Matt Menke7281f872019-06-25 19:29:2522213// Preconnect two sockets with different NetworkIsolationKeys when
22214// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22215// request and make sure the correct socket is used. Loops three times,
22216// expecting to use the first preconnect, second preconnect, and neither.
22217TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22218 base::test::ScopedFeatureList feature_list;
22219 feature_list.InitAndEnableFeature(
22220 features::kPartitionConnectionsByNetworkIsolationKey);
22221
22222 enum class TestCase {
22223 kUseFirstPreconnect,
22224 kUseSecondPreconnect,
22225 kDontUsePreconnect,
22226 };
22227
Shivani Sharma8ae506c2019-07-21 21:08:2722228 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22229 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22230 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
22231 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
22232 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
22233 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2522234
22235 // Test that only preconnects with
22236 for (TestCase test_case :
22237 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22238 TestCase::kDontUsePreconnect}) {
22239 SpdySessionDependencies session_deps;
22240 // Make DNS lookups completely synchronously, so preconnects complete
22241 // immediately.
22242 session_deps.host_resolver->set_synchronous_mode(true);
22243
22244 const MockWrite kMockWrites[] = {
22245 MockWrite(ASYNC, 0,
22246 "GET / HTTP/1.1\r\n"
22247 "Host: www.foo.com\r\n"
22248 "Connection: keep-alive\r\n\r\n"),
22249 };
22250
22251 const MockRead kMockReads[] = {
22252 MockRead(ASYNC, 1,
22253 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22254 "hello"),
22255 };
22256
22257 // Used for the socket that will actually be used, which may or may not be
22258 // one of the preconnects
22259 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22260 kMockReads, kMockWrites);
22261
22262 // Used for the preconnects that won't actually be used.
22263 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22264 base::span<const MockRead>(),
22265 base::span<const MockWrite>());
22266 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22267 base::span<const MockRead>(),
22268 base::span<const MockWrite>());
22269
22270 NetworkIsolationKey network_isolation_key_for_request;
22271
22272 switch (test_case) {
22273 case TestCase::kUseFirstPreconnect:
22274 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22275 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22276 network_isolation_key_for_request = preconnect1_isolation_key;
22277 break;
22278 case TestCase::kUseSecondPreconnect:
22279 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22280 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22281 network_isolation_key_for_request = preconnect2_isolation_key;
22282 break;
22283 case TestCase::kDontUsePreconnect:
22284 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22285 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22286 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22287 network_isolation_key_for_request = not_preconnected_isolation_key;
22288 break;
22289 }
22290
22291 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22292
22293 // Preconnect sockets.
22294 HttpRequestInfo request;
22295 request.method = "GET";
22296 request.url = GURL("http://www.foo.com/");
22297 request.traffic_annotation =
22298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22299
22300 request.network_isolation_key = preconnect1_isolation_key;
22301 session->http_stream_factory()->PreconnectStreams(1, request);
22302
22303 request.network_isolation_key = preconnect2_isolation_key;
22304 session->http_stream_factory()->PreconnectStreams(1, request);
22305
22306 request.network_isolation_key = network_isolation_key_for_request;
22307
22308 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22309
22310 // Make the request.
22311 TestCompletionCallback callback;
22312
22313 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22314
22315 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22316 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22317
22318 rv = callback.WaitForResult();
22319 EXPECT_THAT(rv, IsOk());
22320
22321 const HttpResponseInfo* response = trans.GetResponseInfo();
22322 ASSERT_TRUE(response);
22323 ASSERT_TRUE(response->headers);
22324 EXPECT_EQ(200, response->headers->response_code());
22325
22326 std::string response_data;
22327 rv = ReadTransaction(&trans, &response_data);
22328 EXPECT_THAT(rv, IsOk());
22329 EXPECT_EQ("hello", response_data);
22330
22331 if (test_case != TestCase::kDontUsePreconnect) {
22332 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22333 } else {
22334 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22335 }
22336 }
22337}
22338
David Benjamin6f2da652019-06-26 23:36:3522339// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22340// cache is isolated.
22341TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22342 base::test::ScopedFeatureList feature_list;
22343 feature_list.InitWithFeatures(
22344 {features::kPartitionConnectionsByNetworkIsolationKey,
22345 features::kPartitionSSLSessionsByNetworkIsolationKey},
22346 {});
22347
Shivani Sharma8ae506c2019-07-21 21:08:2722348 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22349 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22350 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22351 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22353
22354 // The server always sends Connection: close, so each request goes over a
22355 // distinct socket.
22356
22357 const MockWrite kWrites1[] = {
22358 MockWrite("GET /1 HTTP/1.1\r\n"
22359 "Host: foo.test\r\n"
22360 "Connection: keep-alive\r\n\r\n")};
22361
22362 const MockRead kReads1[] = {
22363 MockRead("HTTP/1.1 200 OK\r\n"
22364 "Connection: close\r\n"
22365 "Content-Length: 1\r\n\r\n"
22366 "1")};
22367
22368 const MockWrite kWrites2[] = {
22369 MockWrite("GET /2 HTTP/1.1\r\n"
22370 "Host: foo.test\r\n"
22371 "Connection: keep-alive\r\n\r\n")};
22372
22373 const MockRead kReads2[] = {
22374 MockRead("HTTP/1.1 200 OK\r\n"
22375 "Connection: close\r\n"
22376 "Content-Length: 1\r\n\r\n"
22377 "2")};
22378
22379 const MockWrite kWrites3[] = {
22380 MockWrite("GET /3 HTTP/1.1\r\n"
22381 "Host: foo.test\r\n"
22382 "Connection: keep-alive\r\n\r\n")};
22383
22384 const MockRead kReads3[] = {
22385 MockRead("HTTP/1.1 200 OK\r\n"
22386 "Connection: close\r\n"
22387 "Content-Length: 1\r\n\r\n"
22388 "3")};
22389
22390 StaticSocketDataProvider data1(kReads1, kWrites1);
22391 StaticSocketDataProvider data2(kReads2, kWrites2);
22392 StaticSocketDataProvider data3(kReads3, kWrites3);
22393 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22394 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22395 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22396
22397 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22398 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22399 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22400 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22401 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22402 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22403 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22404 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22405 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22408 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22409
22410 TestCompletionCallback callback;
22411 HttpRequestInfo request1;
22412 request1.method = "GET";
22413 request1.url = GURL("https://foo.test/1");
22414 request1.traffic_annotation =
22415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22416 request1.network_isolation_key = kNetworkIsolationKey1;
22417 auto trans1 =
22418 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22419 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22420 EXPECT_THAT(callback.GetResult(rv), IsOk());
22421 std::string response_data1;
22422 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22423 EXPECT_EQ("1", response_data1);
22424 trans1.reset();
22425
22426 HttpRequestInfo request2;
22427 request2.method = "GET";
22428 request2.url = GURL("https://foo.test/2");
22429 request2.traffic_annotation =
22430 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22431 request2.network_isolation_key = kNetworkIsolationKey2;
22432 auto trans2 =
22433 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22434 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22435 EXPECT_THAT(callback.GetResult(rv), IsOk());
22436 std::string response_data2;
22437 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22438 EXPECT_EQ("2", response_data2);
22439 trans2.reset();
22440
22441 HttpRequestInfo request3;
22442 request3.method = "GET";
22443 request3.url = GURL("https://foo.test/3");
22444 request3.traffic_annotation =
22445 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22446 request3.network_isolation_key = kNetworkIsolationKey1;
22447 auto trans3 =
22448 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22449 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22450 EXPECT_THAT(callback.GetResult(rv), IsOk());
22451 std::string response_data3;
22452 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22453 EXPECT_EQ("3", response_data3);
22454 trans3.reset();
22455}
22456
22457// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22458// cache is isolated, for both origins and proxies.
22459TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22460 base::test::ScopedFeatureList feature_list;
22461 feature_list.InitWithFeatures(
22462 {features::kPartitionConnectionsByNetworkIsolationKey,
22463 features::kPartitionSSLSessionsByNetworkIsolationKey},
22464 {});
22465
Nicolas Arciniegad2013f92020-02-07 23:00:5622466 session_deps_.proxy_resolution_service =
22467 ConfiguredProxyResolutionService::CreateFixed(
22468 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin6f2da652019-06-26 23:36:3522469
Shivani Sharma8ae506c2019-07-21 21:08:2722470 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22471 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22472 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22473 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522474 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22475
22476 // Make both a tunneled and non-tunneled request.
22477 HttpRequestInfo request1;
22478 request1.method = "GET";
22479 request1.url = GURL("https://foo.test/1");
22480 request1.traffic_annotation =
22481 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22482 request1.network_isolation_key = kNetworkIsolationKey1;
22483
22484 HttpRequestInfo request2;
22485 request2.method = "GET";
22486 request2.url = GURL("http://foo.test/2");
22487 request2.traffic_annotation =
22488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22489 request2.network_isolation_key = kNetworkIsolationKey2;
22490
22491 const MockWrite kWrites1[] = {
22492 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22493 "Host: foo.test:443\r\n"
22494 "Proxy-Connection: keep-alive\r\n\r\n"),
22495 MockWrite("GET /1 HTTP/1.1\r\n"
22496 "Host: foo.test\r\n"
22497 "Connection: keep-alive\r\n\r\n")};
22498
22499 const MockRead kReads1[] = {
22500 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22501 MockRead("HTTP/1.1 200 OK\r\n"
22502 "Connection: close\r\n"
22503 "Content-Length: 1\r\n\r\n"
22504 "1")};
22505
22506 const MockWrite kWrites2[] = {
22507 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22508 "Host: foo.test\r\n"
22509 "Proxy-Connection: keep-alive\r\n\r\n")};
22510
22511 const MockRead kReads2[] = {
22512 MockRead("HTTP/1.1 200 OK\r\n"
22513 "Connection: close\r\n"
22514 "Content-Length: 1\r\n\r\n"
22515 "2")};
22516
22517 StaticSocketDataProvider data1(kReads1, kWrites1);
22518 StaticSocketDataProvider data2(kReads2, kWrites2);
22519 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22520 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22521 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22522
22523 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22524 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22525 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22526 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22527 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22528 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22529 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22530 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22531 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22534 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22535
22536 TestCompletionCallback callback;
22537 auto trans1 =
22538 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22539 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22540 EXPECT_THAT(callback.GetResult(rv), IsOk());
22541 std::string response_data1;
22542 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22543 EXPECT_EQ("1", response_data1);
22544 trans1.reset();
22545
22546 auto trans2 =
22547 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22548 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22549 EXPECT_THAT(callback.GetResult(rv), IsOk());
22550 std::string response_data2;
22551 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22552 EXPECT_EQ("2", response_data2);
22553 trans2.reset();
22554}
22555
David Benjaminef2f2a5a2019-07-16 19:21:3122556// Test that SSLConfig changes from SSLConfigService are picked up even when
22557// there are live sockets.
22558TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222559 SSLContextConfig ssl_context_config;
22560 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22561 auto ssl_config_service =
22562 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122563 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22564
22565 session_deps_.ssl_config_service = std::move(ssl_config_service);
22566
22567 // Make three requests. Between the second and third, the SSL config will
22568 // change.
22569 HttpRequestInfo request1;
22570 request1.method = "GET";
22571 request1.url = GURL("https://foo.test/1");
22572 request1.traffic_annotation =
22573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22574
22575 HttpRequestInfo request2;
22576 request2.method = "GET";
22577 request2.url = GURL("https://foo.test/2");
22578 request2.traffic_annotation =
22579 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22580
22581 HttpRequestInfo request3;
22582 request3.method = "GET";
22583 request3.url = GURL("https://foo.test/3");
22584 request3.traffic_annotation =
22585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22586
22587 const MockWrite kWrites1[] = {
22588 MockWrite("GET /1 HTTP/1.1\r\n"
22589 "Host: foo.test\r\n"
22590 "Connection: keep-alive\r\n\r\n"),
22591 MockWrite("GET /2 HTTP/1.1\r\n"
22592 "Host: foo.test\r\n"
22593 "Connection: keep-alive\r\n\r\n"),
22594 };
22595
22596 const MockRead kReads1[] = {
22597 MockRead("HTTP/1.1 200 OK\r\n"
22598 "Connection: keep-alive\r\n"
22599 "Content-Length: 1\r\n\r\n"
22600 "1"),
22601 MockRead("HTTP/1.1 200 OK\r\n"
22602 "Connection: keep-alive\r\n"
22603 "Content-Length: 1\r\n\r\n"
22604 "2"),
22605 };
22606
22607 // The third request goes on a different socket because the SSL config has
22608 // changed.
22609 const MockWrite kWrites2[] = {
22610 MockWrite("GET /3 HTTP/1.1\r\n"
22611 "Host: foo.test\r\n"
22612 "Connection: keep-alive\r\n\r\n")};
22613
22614 const MockRead kReads2[] = {
22615 MockRead("HTTP/1.1 200 OK\r\n"
22616 "Connection: keep-alive\r\n"
22617 "Content-Length: 1\r\n\r\n"
22618 "3")};
22619
22620 StaticSocketDataProvider data1(kReads1, kWrites1);
22621 StaticSocketDataProvider data2(kReads2, kWrites2);
22622 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22623 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22624
22625 SSLSocketDataProvider ssl1(ASYNC, OK);
22626 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22627 SSLSocketDataProvider ssl2(ASYNC, OK);
22628 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22629 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22631
22632 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22633
22634 TestCompletionCallback callback;
22635 auto trans1 =
22636 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22637 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22638 EXPECT_THAT(callback.GetResult(rv), IsOk());
22639 std::string response_data1;
22640 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22641 EXPECT_EQ("1", response_data1);
22642 trans1.reset();
22643
22644 auto trans2 =
22645 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22646 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22647 EXPECT_THAT(callback.GetResult(rv), IsOk());
22648 std::string response_data2;
22649 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22650 EXPECT_EQ("2", response_data2);
22651 trans2.reset();
22652
David Benjamin151ec6b2019-08-02 19:38:5222653 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22654 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122655
22656 auto trans3 =
22657 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22658 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22659 EXPECT_THAT(callback.GetResult(rv), IsOk());
22660 std::string response_data3;
22661 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22662 EXPECT_EQ("3", response_data3);
22663 trans3.reset();
22664}
22665
22666TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222667 SSLContextConfig ssl_context_config;
22668 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22669 auto ssl_config_service =
22670 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122671 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22672
22673 session_deps_.ssl_config_service = std::move(ssl_config_service);
22674
22675 HttpRequestInfo request;
22676 request.method = "GET";
22677 request.url = GURL("https://foo.test/1");
22678 request.traffic_annotation =
22679 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22680
22681 // Make a socket which never connects.
22682 StaticSocketDataProvider data({}, {});
22683 session_deps_.socket_factory->AddSocketDataProvider(&data);
22684 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22685 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22687
22688 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22689
22690 TestCompletionCallback callback;
22691 auto trans =
22692 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22693 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22695
David Benjamin151ec6b2019-08-02 19:38:5222696 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22697 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122698
22699 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
22700}
22701
David Benjaminbac8dff2019-08-07 01:30:4122702// Test that HttpNetworkTransaction correctly handles existing sockets when the
22703// server requests a client certificate post-handshake (via a TLS
22704// renegotiation). This is a regression test for https://crbug.com/829184.
22705TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
22706 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
22707 TRAFFIC_ANNOTATION_FOR_TESTS);
22708
22709 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22710 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
22711
22712 std::unique_ptr<FakeClientCertIdentity> identity =
22713 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22714 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22715 ASSERT_TRUE(identity);
22716
22717 // This test will make several requests so that, when the client certificate
22718 // request comes in, we have a socket in use, an idle socket, and a socket for
22719 // an unrelated host.
22720 //
22721 // First, two long-lived requests which do not complete until after the client
22722 // certificate request. This arranges for sockets to be in use during the
22723 // request. They should not be interrupted.
22724 HttpRequestInfo request_long_lived;
22725 request_long_lived.method = "GET";
22726 request_long_lived.url = GURL("https://foo.test/long-lived");
22727 request_long_lived.traffic_annotation = kTrafficAnnotation;
22728
22729 HttpRequestInfo request_long_lived_bar;
22730 request_long_lived_bar.method = "GET";
22731 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
22732 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
22733
22734 // Next, make a request that needs client certificates.
22735 HttpRequestInfo request_auth;
22736 request_auth.method = "GET";
22737 request_auth.url = GURL("https://foo.test/auth");
22738 request_auth.traffic_annotation = kTrafficAnnotation;
22739
22740 // Before responding to the challenge, make a request to an unauthenticated
22741 // endpoint. This will result in an idle socket when the client certificate
22742 // challenge is resolved.
22743 HttpRequestInfo request_unauth;
22744 request_unauth.method = "GET";
22745 request_unauth.url = GURL("https://foo.test/unauth");
22746 request_unauth.traffic_annotation = kTrafficAnnotation;
22747
22748 // After all the preceding requests complete, end with two additional requests
22749 // to ensure pre-authentication foo.test sockets are not used and bar.test
22750 // sockets are unaffected.
22751 HttpRequestInfo request_post_auth;
22752 request_post_auth.method = "GET";
22753 request_post_auth.url = GURL("https://foo.test/post-auth");
22754 request_post_auth.traffic_annotation = kTrafficAnnotation;
22755
22756 HttpRequestInfo request_post_auth_bar;
22757 request_post_auth_bar.method = "GET";
22758 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
22759 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
22760
22761 // The sockets for /long-lived and /unauth complete their request but are
22762 // not allocated for /post-auth or /retry because SSL state has since changed.
22763 const MockWrite kLongLivedWrites[] = {
22764 MockWrite(ASYNC, 0,
22765 "GET /long-lived HTTP/1.1\r\n"
22766 "Host: foo.test\r\n"
22767 "Connection: keep-alive\r\n\r\n"),
22768 };
22769 const MockRead kLongLivedReads[] = {
22770 // Pause so /long-lived completes after the client presents client
22771 // certificates.
22772 MockRead(ASYNC, ERR_IO_PENDING, 1),
22773 MockRead(ASYNC, 2,
22774 "HTTP/1.1 200 OK\r\n"
22775 "Connection: keep-alive\r\n"
22776 "Content-Length: 10\r\n\r\n"
22777 "long-lived"),
22778 };
22779 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
22780 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
22781 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
22782 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
22783
22784 // Requests for bar.test should be unaffected by foo.test and get allocated
22785 // a single socket.
22786 const MockWrite kBarWrites[] = {
22787 MockWrite(ASYNC, 0,
22788 "GET /long-lived HTTP/1.1\r\n"
22789 "Host: bar.test\r\n"
22790 "Connection: keep-alive\r\n\r\n"),
22791 MockWrite(ASYNC, 3,
22792 "GET /post-auth HTTP/1.1\r\n"
22793 "Host: bar.test\r\n"
22794 "Connection: keep-alive\r\n\r\n"),
22795 };
22796 const MockRead kBarReads[] = {
22797 // Pause on /long-lived so it completes after foo.test's authentication.
22798 MockRead(ASYNC, ERR_IO_PENDING, 1),
22799 MockRead(ASYNC, 2,
22800 "HTTP/1.1 200 OK\r\n"
22801 "Connection: keep-alive\r\n"
22802 "Content-Length: 10\r\n\r\n"
22803 "long-lived"),
22804 MockRead(ASYNC, 4,
22805 "HTTP/1.1 200 OK\r\n"
22806 "Connection: keep-alive\r\n"
22807 "Content-Length: 9\r\n\r\n"
22808 "post-auth"),
22809 };
22810 SequencedSocketData data_bar(kBarReads, kBarWrites);
22811 SSLSocketDataProvider ssl_bar(ASYNC, OK);
22812 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
22813 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
22814
22815 // Requesting /auth results in a post-handshake client certificate challenge.
22816 const MockWrite kAuthWrites[] = {
22817 MockWrite(ASYNC, 0,
22818 "GET /auth HTTP/1.1\r\n"
22819 "Host: foo.test\r\n"
22820 "Connection: keep-alive\r\n\r\n"),
22821 };
22822 const MockRead kAuthReads[] = {
22823 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
22824 };
22825 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
22826 SSLSocketDataProvider ssl_auth(ASYNC, OK);
22827 ssl_auth.cert_request_info = cert_request_info.get();
22828 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22829 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22830
22831 // Requesting /unauth completes.
22832 const MockWrite kUnauthWrites[] = {
22833 MockWrite(ASYNC, 0,
22834 "GET /unauth HTTP/1.1\r\n"
22835 "Host: foo.test\r\n"
22836 "Connection: keep-alive\r\n\r\n"),
22837 };
22838 const MockRead kUnauthReads[] = {
22839 MockRead(ASYNC, 1,
22840 "HTTP/1.1 200 OK\r\n"
22841 "Connection: keep-alive\r\n"
22842 "Content-Length: 6\r\n\r\n"
22843 "unauth"),
22844 };
22845 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22846 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22847 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22848 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22849
22850 // When the client certificate is selected, /auth is retried on a new
22851 // connection. In particular, it should not be retried on |data_unauth|,
22852 // which would not honor the new client certificate configuration.
22853 const MockWrite kRetryWrites[] = {
22854 MockWrite(ASYNC, 0,
22855 "GET /auth HTTP/1.1\r\n"
22856 "Host: foo.test\r\n"
22857 "Connection: keep-alive\r\n\r\n"),
22858 };
22859 const MockRead kRetryReads[] = {
22860 MockRead(ASYNC, 1,
22861 "HTTP/1.1 200 OK\r\n"
22862 // Close the connection so we test that /post-auth is not
22863 // allocated to |data_unauth| or |data_long_lived|.
22864 "Connection: close\r\n"
22865 "Content-Length: 4\r\n\r\n"
22866 "auth"),
22867 };
22868 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22869 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22870 ssl_retry.expected_send_client_cert = true;
22871 ssl_retry.expected_client_cert = identity->certificate();
22872 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22873 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22874
22875 // /post-auth gets its own socket.
22876 const MockWrite kPostAuthWrites[] = {
22877 MockWrite(ASYNC, 0,
22878 "GET /post-auth HTTP/1.1\r\n"
22879 "Host: foo.test\r\n"
22880 "Connection: keep-alive\r\n\r\n"),
22881 };
22882 const MockRead kPostAuthReads[] = {
22883 MockRead(ASYNC, 1,
22884 "HTTP/1.1 200 OK\r\n"
22885 "Connection: keep-alive\r\n"
22886 "Content-Length: 9\r\n\r\n"
22887 "post-auth"),
22888 };
22889 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22890 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22891 ssl_post_auth.expected_send_client_cert = true;
22892 ssl_post_auth.expected_client_cert = identity->certificate();
22893 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22895
22896 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22897
22898 // Start the two long-lived requests.
22899 TestCompletionCallback callback_long_lived;
22900 auto trans_long_lived =
22901 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22902 int rv = trans_long_lived->Start(
22903 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22904 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22905 data_long_lived.RunUntilPaused();
22906
22907 TestCompletionCallback callback_long_lived_bar;
22908 auto trans_long_lived_bar =
22909 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22910 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22911 callback_long_lived_bar.callback(),
22912 NetLogWithSource());
22913 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22914 data_bar.RunUntilPaused();
22915
22916 // Request /auth. This gives a client certificate challenge.
22917 TestCompletionCallback callback_auth;
22918 auto trans_auth =
22919 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22920 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22921 NetLogWithSource());
22922 EXPECT_THAT(callback_auth.GetResult(rv),
22923 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22924
22925 // Make an unauthenticated request. This completes.
22926 TestCompletionCallback callback_unauth;
22927 auto trans_unauth =
22928 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22929 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22930 NetLogWithSource());
22931 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22932 std::string response_unauth;
22933 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22934 EXPECT_EQ("unauth", response_unauth);
22935 trans_unauth.reset();
22936
22937 // Complete the authenticated request.
22938 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22939 identity->ssl_private_key(),
22940 callback_auth.callback());
22941 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22942 std::string response_auth;
22943 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22944 EXPECT_EQ("auth", response_auth);
22945 trans_auth.reset();
22946
22947 // Complete the long-lived requests.
22948 data_long_lived.Resume();
22949 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22950 std::string response_long_lived;
22951 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22952 IsOk());
22953 EXPECT_EQ("long-lived", response_long_lived);
22954 trans_long_lived.reset();
22955
22956 data_bar.Resume();
22957 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22958 std::string response_long_lived_bar;
22959 EXPECT_THAT(
22960 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22961 IsOk());
22962 EXPECT_EQ("long-lived", response_long_lived_bar);
22963 trans_long_lived_bar.reset();
22964
22965 // Run the post-authentication requests.
22966 TestCompletionCallback callback_post_auth;
22967 auto trans_post_auth =
22968 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22969 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22970 NetLogWithSource());
22971 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22972 std::string response_post_auth;
22973 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22974 IsOk());
22975 EXPECT_EQ("post-auth", response_post_auth);
22976 trans_post_auth.reset();
22977
22978 TestCompletionCallback callback_post_auth_bar;
22979 auto trans_post_auth_bar =
22980 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22981 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22982 callback_post_auth_bar.callback(),
22983 NetLogWithSource());
22984 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22985 std::string response_post_auth_bar;
22986 EXPECT_THAT(
22987 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22988 IsOk());
22989 EXPECT_EQ("post-auth", response_post_auth_bar);
22990 trans_post_auth_bar.reset();
22991}
22992
[email protected]89ceba9a2009-03-21 03:46:0622993} // namespace net