blob: cfadcf515c19277c464dcf21e76e78c24157a4b5 [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"
Matt Menkeecfecfc72019-02-05 19:15:2834#include "base/test/scoped_task_environment.h"
Douglas Creager134b52e2018-11-09 18:00:1435#include "base/test/simple_test_clock.h"
36#include "base/test/simple_test_tick_clock.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"
aberentbba302d2015-12-03 10:20:1965#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5766#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5267#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5668#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0469#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2470#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1371#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2672#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5773#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3874#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1975#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0776#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0077#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1978#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5179#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4680#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4081#include "net/proxy_resolution/mock_proxy_resolver.h"
82#include "net/proxy_resolution/proxy_config_service_fixed.h"
83#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0384#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4085#include "net/proxy_resolution/proxy_resolver.h"
86#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4487#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1588#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0389#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3690#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4791#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0292#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0793#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0494#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4495#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1296#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4497#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5898#include "net/spdy/spdy_session.h"
99#include "net/spdy/spdy_session_pool.h"
100#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04101#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57102#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31103#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03104#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57105#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54106#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52107#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11108#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01109#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43110#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:01111#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14112#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23113#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00114#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44115#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06116#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18117#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52118#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15119#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27120#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52121
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37122#if defined(NTLM_PORTABLE)
123#include "base/base64.h"
124#include "net/ntlm/ntlm_test_data.h"
125#endif
126
Douglas Creager3cb042052018-11-06 23:08:52127#if BUILDFLAG(ENABLE_REPORTING)
128#include "net/network_error_logging/network_error_logging_service.h"
129#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14130#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10131#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14132#include "net/reporting/reporting_header_parser.h"
133#include "net/reporting/reporting_service.h"
134#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52135#endif // BUILDFLAG(ENABLE_REPORTING)
136
robpercival214763f2016-07-01 23:27:01137using net::test::IsError;
138using net::test::IsOk;
139
[email protected]ad65a3e2013-12-25 18:18:01140using base::ASCIIToUTF16;
141
David Benjamin3b94b0f2019-04-25 23:07:52142using testing::AnyOf;
143
initial.commit586acc5fe2008-07-26 22:42:52144//-----------------------------------------------------------------------------
145
ttuttle859dc7a2015-04-23 19:42:29146namespace net {
147
[email protected]13c8a092010-07-29 06:15:44148namespace {
149
[email protected]42cba2fb2013-03-29 19:58:57150const base::string16 kBar(ASCIIToUTF16("bar"));
151const base::string16 kBar2(ASCIIToUTF16("bar2"));
152const base::string16 kBar3(ASCIIToUTF16("bar3"));
153const base::string16 kBaz(ASCIIToUTF16("baz"));
154const base::string16 kFirst(ASCIIToUTF16("first"));
155const base::string16 kFoo(ASCIIToUTF16("foo"));
156const base::string16 kFoo2(ASCIIToUTF16("foo2"));
157const base::string16 kFoo3(ASCIIToUTF16("foo3"));
158const base::string16 kFou(ASCIIToUTF16("fou"));
159const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57160const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44161
bnc2df4b522016-07-08 18:17:43162const char kAlternativeServiceHttpHeader[] =
163 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
164
ttuttle859dc7a2015-04-23 19:42:29165int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40166 return session
167 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
168 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29169 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02170}
171
ttuttle859dc7a2015-04-23 19:42:29172bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40173 return session
174 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
175 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29176 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52177}
178
[email protected]f3da152d2012-06-02 01:00:57179// Takes in a Value created from a NetLogHttpResponseParameter, and returns
180// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54181// of double quotes for easier comparison.
182std::string GetHeaders(const base::Value& params) {
183 if (!params.is_dict())
184 return "";
185 const base::Value* header_list = params.FindListKey("headers");
186 if (!header_list)
187 return "";
188 std::string headers;
189 base::JSONWriter::Write(*header_list, &headers);
190 base::ReplaceChars(headers, "\"", "'", &headers);
191 return headers;
[email protected]f3da152d2012-06-02 01:00:57192}
193
[email protected]029c83b62013-01-24 05:28:20194// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
195// used.
ttuttle859dc7a2015-04-23 19:42:29196void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19198 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25199
[email protected]029c83b62013-01-24 05:28:20200 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
201 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
202
ttuttle859dc7a2015-04-23 19:42:29203 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20204 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25205
206 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25207
[email protected]3b23a222013-05-15 21:33:25208 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25209 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
210 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25211 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25212}
213
[email protected]029c83b62013-01-24 05:28:20214// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
215// used.
ttuttle859dc7a2015-04-23 19:42:29216void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25217 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20218 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19219 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20220
221 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
222 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
223
ttuttle859dc7a2015-04-23 19:42:29224 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
225 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20226 EXPECT_LE(load_timing_info.connect_timing.connect_end,
227 load_timing_info.send_start);
228
229 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20230
[email protected]3b23a222013-05-15 21:33:25231 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20232 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
233 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25234 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20235}
236
237// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
238// used.
ttuttle859dc7a2015-04-23 19:42:29239void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20240 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19241 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20242
ttuttle859dc7a2015-04-23 19:42:29243 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20244
245 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
246 EXPECT_LE(load_timing_info.proxy_resolve_start,
247 load_timing_info.proxy_resolve_end);
248 EXPECT_LE(load_timing_info.proxy_resolve_end,
249 load_timing_info.send_start);
250 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20251
[email protected]3b23a222013-05-15 21:33:25252 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20253 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
254 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25255 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20256}
257
258// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
259// used.
ttuttle859dc7a2015-04-23 19:42:29260void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20261 int connect_timing_flags) {
262 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19263 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20264
265 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
266 EXPECT_LE(load_timing_info.proxy_resolve_start,
267 load_timing_info.proxy_resolve_end);
268 EXPECT_LE(load_timing_info.proxy_resolve_end,
269 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29270 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
271 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20272 EXPECT_LE(load_timing_info.connect_timing.connect_end,
273 load_timing_info.send_start);
274
275 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20276
[email protected]3b23a222013-05-15 21:33:25277 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20278 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
279 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25280 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25281}
282
Matt Menke2436b2f2018-12-11 18:07:11283// ProxyResolver that records URLs passed to it, and that can be told what
284// result to return.
285class CapturingProxyResolver : public ProxyResolver {
286 public:
287 CapturingProxyResolver()
288 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
289 ~CapturingProxyResolver() override = default;
290
291 int GetProxyForURL(const GURL& url,
292 ProxyInfo* results,
293 CompletionOnceCallback callback,
294 std::unique_ptr<Request>* request,
295 const NetLogWithSource& net_log) override {
296 results->UseProxyServer(proxy_server_);
297 resolved_.push_back(url);
298 return OK;
299 }
300
301 // Sets whether the resolver should use direct connections, instead of a
302 // proxy.
303 void set_proxy_server(ProxyServer proxy_server) {
304 proxy_server_ = proxy_server;
305 }
306
307 const std::vector<GURL>& resolved() const { return resolved_; }
308
309 private:
310 std::vector<GURL> resolved_;
311
312 ProxyServer proxy_server_;
313
314 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
315};
316
317class CapturingProxyResolverFactory : public ProxyResolverFactory {
318 public:
319 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
320 : ProxyResolverFactory(false), resolver_(resolver) {}
321
322 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
323 std::unique_ptr<ProxyResolver>* resolver,
324 CompletionOnceCallback callback,
325 std::unique_ptr<Request>* request) override {
326 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
327 return OK;
328 }
329
330 private:
331 ProxyResolver* resolver_;
332};
333
danakj1fd259a02016-04-16 03:17:09334std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42335 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34336 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14337}
338
xunjieli96f2a402017-06-05 17:24:27339class FailingProxyResolverFactory : public ProxyResolverFactory {
340 public:
341 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
342
343 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42344 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
345 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17346 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42347 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27348 return ERR_PAC_SCRIPT_FAILED;
349 }
350};
351
[email protected]448d4ca52012-03-04 04:12:23352} // namespace
353
Bence Béky98447b12018-05-08 03:14:01354class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05355 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03356 public:
bncd16676a2016-07-20 16:23:01357 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03358 // Important to restore the per-pool limit first, since the pool limit must
359 // always be greater than group limit, and the tests reduce both limits.
360 ClientSocketPoolManager::set_max_sockets_per_pool(
361 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
362 ClientSocketPoolManager::set_max_sockets_per_group(
363 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
364 }
365
[email protected]e3ceb682011-06-28 23:55:46366 protected:
[email protected]23e482282013-06-14 16:08:02367 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05368 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36369 dummy_connect_job_params_(
370 nullptr /* client_socket_factory */,
371 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40372 nullptr /* http_auth_cache */,
373 nullptr /* http_auth_handler_factory */,
374 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13375 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40376 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36377 nullptr /* proxy_delegate */,
378 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18379 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36380 nullptr /* socket_performance_watcher_factory */,
381 nullptr /* network_quality_estimator */,
382 nullptr /* net_log */,
383 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56384 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15385 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03386 HttpNetworkSession::NORMAL_SOCKET_POOL)),
387 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
388 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28389 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03390 }
[email protected]bb88e1d32013-05-03 23:11:07391
[email protected]e3ceb682011-06-28 23:55:46392 struct SimpleGetHelperResult {
393 int rv;
394 std::string status_line;
395 std::string response_data;
sclittlefb249892015-09-10 21:33:22396 int64_t total_received_bytes;
397 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25398 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47399 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59400 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46401 };
402
dcheng67be2b1f2014-10-27 21:47:29403 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50404 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55405 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56406 // Set an initial delay to ensure that the first call to TimeTicks::Now()
407 // before incrementing the counter does not return a null value.
408 FastForwardBy(TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54409 }
410
dcheng67be2b1f2014-10-27 21:47:29411 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50412 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55413 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09414 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55415 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09416 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50417 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55418 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09419 }
420
Andrew Comminos1f2ff1cc2018-12-14 05:22:38421 void Check100ResponseTiming(bool use_spdy);
422
[email protected]202965992011-12-07 23:04:51423 // Either |write_failure| specifies a write failure or |read_failure|
424 // specifies a read failure when using a reused socket. In either case, the
425 // failure should cause the network transaction to resend the request, and the
426 // other argument should be NULL.
427 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
428 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52429
[email protected]a34f61ee2014-03-18 20:59:49430 // 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 PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10435 const MockRead* read_failure,
436 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49437
Ryan Sleevib8d7ea02018-05-07 20:01:01438 SimpleGetHelperResult SimpleGetHelperForData(
439 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15440 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52441
[email protected]ff007e162009-05-23 09:13:15442 HttpRequestInfo request;
443 request.method = "GET";
bncce36dca22015-04-21 22:11:23444 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10445 request.traffic_annotation =
446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52447
vishal.b62985ca92015-04-17 08:45:51448 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07449 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09450 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16451 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27452
Ryan Sleevib8d7ea02018-05-07 20:01:01453 for (auto* provider : providers) {
454 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29455 }
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]49639fa2011-12-20 23:22:41457 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52458
eroman24bc6a12015-05-06 19:55:48459 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16460 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52462
[email protected]ff007e162009-05-23 09:13:15463 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16464 out.total_received_bytes = trans.GetTotalReceivedBytes();
465 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25466
467 // Even in the failure cases that use this function, connections are always
468 // successfully established before the error.
bnc691fda62016-08-12 00:43:16469 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25470 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
471
[email protected]ff007e162009-05-23 09:13:15472 if (out.rv != OK)
473 return out;
474
bnc691fda62016-08-12 00:43:16475 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50476 // Can't use ASSERT_* inside helper functions like this, so
477 // return an error.
wezca1070932016-05-26 20:30:52478 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50479 out.rv = ERR_UNEXPECTED;
480 return out;
481 }
[email protected]ff007e162009-05-23 09:13:15482 out.status_line = response->headers->GetStatusLine();
483
Tsuyoshi Horo01faed62019-02-20 22:11:37484 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
485 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19486
ttuttled9dbc652015-09-29 20:00:59487 bool got_endpoint =
bnc691fda62016-08-12 00:43:16488 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59489 EXPECT_EQ(got_endpoint,
490 out.remote_endpoint_after_start.address().size() > 0);
491
bnc691fda62016-08-12 00:43:16492 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01493 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40494
Eric Roman79cc7552019-07-19 02:17:54495 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39496 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00497 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
498 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39499 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00500 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
501 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15502
Eric Roman79cc7552019-07-19 02:17:54503 EXPECT_EQ("GET / HTTP/1.1\r\n",
504 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57505
[email protected]79e1fd62013-06-20 06:50:04506 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:16507 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:04508 std::string value;
509 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23510 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04511 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
512 EXPECT_EQ("keep-alive", value);
513
bncce36dca22015-04-21 22:11:23514 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54515 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40516
bnc691fda62016-08-12 00:43:16517 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22518 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16519 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22520
bnc691fda62016-08-12 00:43:16521 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47522 return out;
[email protected]ff007e162009-05-23 09:13:15523 }
initial.commit586acc5fe2008-07-26 22:42:52524
Ryan Sleevib8d7ea02018-05-07 20:01:01525 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22526 MockWrite data_writes[] = {
527 MockWrite("GET / HTTP/1.1\r\n"
528 "Host: www.example.org\r\n"
529 "Connection: keep-alive\r\n\r\n"),
530 };
[email protected]5a60c8b2011-10-19 20:14:29531
Ryan Sleevib8d7ea02018-05-07 20:01:01532 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22533 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01534 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22535
Ryan Sleevib8d7ea02018-05-07 20:01:01536 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22537 return out;
[email protected]b8015c42013-12-24 15:18:19538 }
539
bnc032658ba2016-09-26 18:17:15540 void AddSSLSocketData() {
541 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49542 ssl_.ssl_info.cert =
543 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
544 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15545 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
546 }
547
[email protected]ff007e162009-05-23 09:13:15548 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
549 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52550
[email protected]ff007e162009-05-23 09:13:15551 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07552
[email protected]bb88e1d32013-05-03 23:11:07553 void CheckErrorIsPassedBack(int error, IoMode mode);
554
Matt Menked6fd2a52019-03-20 06:14:36555 const CommonConnectJobParams dummy_connect_job_params_;
556
Douglas Creager134b52e2018-11-09 18:00:14557 // These clocks are defined here, even though they're only used in the
558 // Reporting tests below, since they need to be destroyed after
559 // |session_deps_|.
560 base::SimpleTestClock clock_;
561 base::SimpleTestTickClock tick_clock_;
562
[email protected]4bd46222013-05-14 19:32:23563 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07564 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15565 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03566
567 // Original socket limits. Some tests set these. Safest to always restore
568 // them once each test has been run.
569 int old_max_group_sockets_;
570 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15571};
[email protected]231d5a32008-09-13 00:45:27572
[email protected]448d4ca52012-03-04 04:12:23573namespace {
574
ryansturm49a8cb12016-06-15 16:51:09575class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27576 public:
ryansturm49a8cb12016-06-15 16:51:09577 BeforeHeadersSentHandler()
578 : observed_before_headers_sent_with_proxy_(false),
579 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27580
ryansturm49a8cb12016-06-15 16:51:09581 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
582 HttpRequestHeaders* request_headers) {
583 observed_before_headers_sent_ = true;
584 if (!proxy_info.is_http() && !proxy_info.is_https() &&
585 !proxy_info.is_quic()) {
586 return;
587 }
588 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27589 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
590 }
591
ryansturm49a8cb12016-06-15 16:51:09592 bool observed_before_headers_sent_with_proxy() const {
593 return observed_before_headers_sent_with_proxy_;
594 }
595
596 bool observed_before_headers_sent() const {
597 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27598 }
599
600 std::string observed_proxy_server_uri() const {
601 return observed_proxy_server_uri_;
602 }
603
604 private:
ryansturm49a8cb12016-06-15 16:51:09605 bool observed_before_headers_sent_with_proxy_;
606 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27607 std::string observed_proxy_server_uri_;
608
ryansturm49a8cb12016-06-15 16:51:09609 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27610};
611
[email protected]15a5ccf82008-10-23 19:57:43612// Fill |str| with a long header list that consumes >= |size| bytes.
613void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51614 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19615 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
616 const int sizeof_row = strlen(row);
617 const int num_rows = static_cast<int>(
618 ceil(static_cast<float>(size) / sizeof_row));
619 const int sizeof_data = num_rows * sizeof_row;
620 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43621 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51622
[email protected]4ddaf2502008-10-23 18:26:19623 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43624 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19625}
626
thakis84dff942015-07-28 20:47:38627#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09628uint64_t MockGetMSTime() {
629 // Tue, 23 May 2017 20:13:07 +0000
630 return 131400439870000000;
631}
632
[email protected]385a4672009-03-11 22:21:29633// Alternative functions that eliminate randomness and dependency on the local
634// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37635void MockGenerateRandom(uint8_t* output, size_t n) {
636 // This is set to 0xaa because the client challenge for testing in
637 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
638 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29639}
640
[email protected]fe2bc6a2009-03-23 16:52:20641std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37642 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29643}
thakis84dff942015-07-28 20:47:38644#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29645
Matt Menked6fd2a52019-03-20 06:14:36646class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31647 public:
Matt Menked6fd2a52019-03-20 06:14:36648 explicit CaptureGroupIdTransportSocketPool(
649 const CommonConnectJobParams* common_connect_job_params)
650 : TransportClientSocketPool(0,
651 0,
652 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36653 ProxyServer::Direct(),
654 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52655 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18656
Matt Menkef6edce752019-03-19 17:21:56657 const ClientSocketPool::GroupId& last_group_id_received() const {
658 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49659 }
660
Tarun Bansal162eabe52018-01-20 01:16:39661 bool socket_requested() const { return socket_requested_; }
662
Matt Menke28ac03e2019-02-25 22:25:50663 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56664 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03665 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28666 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50667 RequestPriority priority,
668 const SocketTag& socket_tag,
669 ClientSocketPool::RespectLimits respect_limits,
670 ClientSocketHandle* handle,
671 CompletionOnceCallback callback,
672 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
673 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56674 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39675 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31676 return ERR_IO_PENDING;
677 }
Matt Menkef6edce752019-03-19 17:21:56678 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21679 ClientSocketHandle* handle,
680 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56681 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09682 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24683 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57684 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56685 void CloseIdleSocketsInGroup(
686 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57687 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56688 size_t IdleSocketCountInGroup(
689 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31690 return 0;
691 }
Matt Menkef6edce752019-03-19 17:21:56692 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57693 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31694 return LOAD_STATE_IDLE;
695 }
[email protected]d80a4322009-08-14 07:07:49696
697 private:
Matt Menkef6edce752019-03-19 17:21:56698 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39699 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31700};
701
[email protected]231d5a32008-09-13 00:45:27702//-----------------------------------------------------------------------------
703
[email protected]79cb5c12011-09-12 13:12:04704// Helper functions for validating that AuthChallengeInfo's are correctly
705// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58706bool CheckBasicServerAuth(
707 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04708 if (!auth_challenge)
709 return false;
710 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43711 EXPECT_EQ("http://www.example.org", 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
David Benjamin2eb827f2019-04-29 18:31:04717bool CheckBasicSecureServerAuth(
718 const base::Optional<AuthChallengeInfo>& auth_challenge) {
719 if (!auth_challenge)
720 return false;
721 EXPECT_FALSE(auth_challenge->is_proxy);
722 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
723 EXPECT_EQ("MyRealm1", auth_challenge->realm);
724 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
725 return true;
726}
727
Emily Starkf2c9bbd2019-04-09 17:08:58728bool CheckBasicProxyAuth(
729 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04730 if (!auth_challenge)
731 return false;
732 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43733 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
734 EXPECT_EQ("MyRealm1", auth_challenge->realm);
735 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
736 return true;
737}
738
Emily Starkf2c9bbd2019-04-09 17:08:58739bool CheckBasicSecureProxyAuth(
740 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43741 if (!auth_challenge)
742 return false;
743 EXPECT_TRUE(auth_challenge->is_proxy);
744 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04745 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19746 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04747 return true;
748}
749
Emily Starkf2c9bbd2019-04-09 17:08:58750bool CheckDigestServerAuth(
751 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04752 if (!auth_challenge)
753 return false;
754 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43755 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04756 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19757 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04758 return true;
759}
760
thakis84dff942015-07-28 20:47:38761#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58762bool CheckNTLMServerAuth(
763 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04764 if (!auth_challenge)
765 return false;
766 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55767 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04768 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19769 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04770 return true;
771}
David Benjamin5cb91132018-04-06 05:54:49772
Emily Starkf2c9bbd2019-04-09 17:08:58773bool CheckNTLMProxyAuth(
774 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49775 if (!auth_challenge)
776 return false;
777 EXPECT_TRUE(auth_challenge->is_proxy);
778 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
779 EXPECT_EQ(std::string(), auth_challenge->realm);
780 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
781 return true;
782}
thakis84dff942015-07-28 20:47:38783#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04784
[email protected]448d4ca52012-03-04 04:12:23785} // namespace
786
Shivani Sharma8ae506c2019-07-21 21:08:27787// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
788// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
789
bncd16676a2016-07-20 16:23:01790TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09791 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16792 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27793}
794
bncd16676a2016-07-20 16:23:01795TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27796 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35797 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
798 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06799 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27800 };
Ryan Sleevib8d7ea02018-05-07 20:01:01801 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01802 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27803 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
804 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01805 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22806 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47807 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59808
809 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27810}
811
812// Response with no status line.
bncd16676a2016-07-20 16:23:01813TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27814 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06816 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27817 };
Ryan Sleevib8d7ea02018-05-07 20:01:01818 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41819 EXPECT_THAT(out.rv, IsOk());
820 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
821 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01822 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41823 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27824}
825
mmenkea7da6da2016-09-01 21:56:52826// Response with no status line, and a weird port. Should fail by default.
827TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
828 MockRead data_reads[] = {
829 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
830 };
831
Ryan Sleevib8d7ea02018-05-07 20:01:01832 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52833 session_deps_.socket_factory->AddSocketDataProvider(&data);
834
835 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
836
krasinc06a72a2016-12-21 03:42:46837 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58838 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19839 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52840
mmenkea7da6da2016-09-01 21:56:52841 request.method = "GET";
842 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10843 request.traffic_annotation =
844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
845
mmenkea7da6da2016-09-01 21:56:52846 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20847 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52848 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
849}
850
Shivani Sharmafdcaefd2017-11-02 00:12:26851// Tests that request info can be destroyed after the headers phase is complete.
852TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
854 auto trans =
855 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
856
857 MockRead data_reads[] = {
858 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
859 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
860 };
Ryan Sleevib8d7ea02018-05-07 20:01:01861 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26862 session_deps_.socket_factory->AddSocketDataProvider(&data);
863
864 TestCompletionCallback callback;
865
866 {
867 auto request = std::make_unique<HttpRequestInfo>();
868 request->method = "GET";
869 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10870 request->traffic_annotation =
871 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26872
873 int rv =
874 trans->Start(request.get(), callback.callback(), NetLogWithSource());
875
876 EXPECT_THAT(callback.GetResult(rv), IsOk());
877 } // Let request info be destroyed.
878
879 trans.reset();
880}
881
mmenkea7da6da2016-09-01 21:56:52882// Response with no status line, and a weird port. Option to allow weird ports
883// enabled.
884TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPortAllowed) {
885 MockRead data_reads[] = {
886 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
887 };
888
Ryan Sleevib8d7ea02018-05-07 20:01:01889 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52890 session_deps_.socket_factory->AddSocketDataProvider(&data);
891 session_deps_.http_09_on_non_default_ports_enabled = true;
892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
893
krasinc06a72a2016-12-21 03:42:46894 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58895 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19896 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52897
mmenkea7da6da2016-09-01 21:56:52898 request.method = "GET";
899 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10900 request.traffic_annotation =
901 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
902
mmenkea7da6da2016-09-01 21:56:52903 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20904 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52905 EXPECT_THAT(callback.GetResult(rv), IsOk());
906
907 const HttpResponseInfo* info = trans->GetResponseInfo();
908 ASSERT_TRUE(info->headers);
909 EXPECT_EQ("HTTP/0.9 200 OK", info->headers->GetStatusLine());
910
911 // Don't bother to read the body - that's verified elsewhere, important thing
912 // is that the option to allow HTTP/0.9 on non-default ports is respected.
913}
914
[email protected]231d5a32008-09-13 00:45:27915// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01916TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27917 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35918 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06919 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27920 };
Ryan Sleevib8d7ea02018-05-07 20:01:01921 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01922 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27923 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
924 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01925 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22926 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27927}
928
929// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01930TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27931 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35932 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06933 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27934 };
Ryan Sleevib8d7ea02018-05-07 20:01:01935 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01936 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27937 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
938 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01939 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22940 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27941}
942
943// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01944TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27945 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35946 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06947 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27948 };
Ryan Sleevib8d7ea02018-05-07 20:01:01949 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41950 EXPECT_THAT(out.rv, IsOk());
951 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
952 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01953 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41954 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27955}
956
957// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01958TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27959 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35960 MockRead("\n"),
961 MockRead("\n"),
962 MockRead("Q"),
963 MockRead("J"),
964 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06965 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27966 };
Ryan Sleevib8d7ea02018-05-07 20:01:01967 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01968 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27969 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
970 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01971 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22972 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27973}
974
975// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01976TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27977 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35978 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06979 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27980 };
Ryan Sleevib8d7ea02018-05-07 20:01:01981 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41982 EXPECT_THAT(out.rv, IsOk());
983 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
984 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01985 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41986 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52987}
988
[email protected]f9d44aa2008-09-23 23:57:17989// Simulate a 204 response, lacking a Content-Length header, sent over a
990// persistent connection. The response should still terminate since a 204
991// cannot have a response body.
bncd16676a2016-07-20 16:23:01992TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19993 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17994 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35995 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19996 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06997 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17998 };
Ryan Sleevib8d7ea02018-05-07 20:01:01999 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011000 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171001 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1002 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011003 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221004 int64_t response_size = reads_size - strlen(junk);
1005 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171006}
1007
[email protected]0877e3d2009-10-17 22:29:571008// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011009TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191010 std::string final_chunk = "0\r\n\r\n";
1011 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1012 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571013 MockRead data_reads[] = {
1014 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1015 MockRead("5\r\nHello\r\n"),
1016 MockRead("1\r\n"),
1017 MockRead(" \r\n"),
1018 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191019 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061020 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571021 };
Ryan Sleevib8d7ea02018-05-07 20:01:011022 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011023 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571024 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1025 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011026 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221027 int64_t response_size = reads_size - extra_data.size();
1028 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571029}
1030
[email protected]9fe44f52010-09-23 18:36:001031// Next tests deal with http://crbug.com/56344.
1032
bncd16676a2016-07-20 16:23:011033TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001034 MultipleContentLengthHeadersNoTransferEncoding) {
1035 MockRead data_reads[] = {
1036 MockRead("HTTP/1.1 200 OK\r\n"),
1037 MockRead("Content-Length: 10\r\n"),
1038 MockRead("Content-Length: 5\r\n\r\n"),
1039 };
Ryan Sleevib8d7ea02018-05-07 20:01:011040 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011041 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001042}
1043
bncd16676a2016-07-20 16:23:011044TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041045 DuplicateContentLengthHeadersNoTransferEncoding) {
1046 MockRead data_reads[] = {
1047 MockRead("HTTP/1.1 200 OK\r\n"),
1048 MockRead("Content-Length: 5\r\n"),
1049 MockRead("Content-Length: 5\r\n\r\n"),
1050 MockRead("Hello"),
1051 };
Ryan Sleevib8d7ea02018-05-07 20:01:011052 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011053 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041054 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1055 EXPECT_EQ("Hello", out.response_data);
1056}
1057
bncd16676a2016-07-20 16:23:011058TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041059 ComplexContentLengthHeadersNoTransferEncoding) {
1060 // More than 2 dupes.
1061 {
1062 MockRead data_reads[] = {
1063 MockRead("HTTP/1.1 200 OK\r\n"),
1064 MockRead("Content-Length: 5\r\n"),
1065 MockRead("Content-Length: 5\r\n"),
1066 MockRead("Content-Length: 5\r\n\r\n"),
1067 MockRead("Hello"),
1068 };
Ryan Sleevib8d7ea02018-05-07 20:01:011069 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011070 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041071 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1072 EXPECT_EQ("Hello", out.response_data);
1073 }
1074 // HTTP/1.0
1075 {
1076 MockRead data_reads[] = {
1077 MockRead("HTTP/1.0 200 OK\r\n"),
1078 MockRead("Content-Length: 5\r\n"),
1079 MockRead("Content-Length: 5\r\n"),
1080 MockRead("Content-Length: 5\r\n\r\n"),
1081 MockRead("Hello"),
1082 };
Ryan Sleevib8d7ea02018-05-07 20:01:011083 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011084 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041085 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1086 EXPECT_EQ("Hello", out.response_data);
1087 }
1088 // 2 dupes and one mismatched.
1089 {
1090 MockRead data_reads[] = {
1091 MockRead("HTTP/1.1 200 OK\r\n"),
1092 MockRead("Content-Length: 10\r\n"),
1093 MockRead("Content-Length: 10\r\n"),
1094 MockRead("Content-Length: 5\r\n\r\n"),
1095 };
Ryan Sleevib8d7ea02018-05-07 20:01:011096 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011097 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041098 }
1099}
1100
bncd16676a2016-07-20 16:23:011101TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001102 MultipleContentLengthHeadersTransferEncoding) {
1103 MockRead data_reads[] = {
1104 MockRead("HTTP/1.1 200 OK\r\n"),
1105 MockRead("Content-Length: 666\r\n"),
1106 MockRead("Content-Length: 1337\r\n"),
1107 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1108 MockRead("5\r\nHello\r\n"),
1109 MockRead("1\r\n"),
1110 MockRead(" \r\n"),
1111 MockRead("5\r\nworld\r\n"),
1112 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061113 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001114 };
Ryan Sleevib8d7ea02018-05-07 20:01:011115 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011116 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001117 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1118 EXPECT_EQ("Hello world", out.response_data);
1119}
1120
[email protected]1628fe92011-10-04 23:04:551121// Next tests deal with http://crbug.com/98895.
1122
1123// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011124TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551125 MockRead data_reads[] = {
1126 MockRead("HTTP/1.1 200 OK\r\n"),
1127 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1128 MockRead("Content-Length: 5\r\n\r\n"),
1129 MockRead("Hello"),
1130 };
Ryan Sleevib8d7ea02018-05-07 20:01:011131 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011132 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551133 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1134 EXPECT_EQ("Hello", out.response_data);
1135}
1136
[email protected]54a9c6e52012-03-21 20:10:591137// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011138TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551139 MockRead data_reads[] = {
1140 MockRead("HTTP/1.1 200 OK\r\n"),
1141 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1142 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1143 MockRead("Content-Length: 5\r\n\r\n"),
1144 MockRead("Hello"),
1145 };
Ryan Sleevib8d7ea02018-05-07 20:01:011146 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011147 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591148 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1149 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551150}
1151
1152// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011153TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551154 MockRead data_reads[] = {
1155 MockRead("HTTP/1.1 200 OK\r\n"),
1156 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1157 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1158 MockRead("Content-Length: 5\r\n\r\n"),
1159 MockRead("Hello"),
1160 };
Ryan Sleevib8d7ea02018-05-07 20:01:011161 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011162 EXPECT_THAT(out.rv,
1163 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551164}
1165
[email protected]54a9c6e52012-03-21 20:10:591166// Checks that two identical Location headers result in no error.
1167// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011168TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551169 MockRead data_reads[] = {
1170 MockRead("HTTP/1.1 302 Redirect\r\n"),
1171 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591172 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551173 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061174 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551175 };
1176
1177 HttpRequestInfo request;
1178 request.method = "GET";
1179 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101180 request.traffic_annotation =
1181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551182
danakj1fd259a02016-04-16 03:17:091183 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161184 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551185
Ryan Sleevib8d7ea02018-05-07 20:01:011186 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071187 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551188
[email protected]49639fa2011-12-20 23:22:411189 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551190
tfarina42834112016-09-22 13:38:201191 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551193
robpercival214763f2016-07-01 23:27:011194 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551195
bnc691fda62016-08-12 00:43:161196 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521197 ASSERT_TRUE(response);
1198 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551199 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1200 std::string url;
1201 EXPECT_TRUE(response->headers->IsRedirect(&url));
1202 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471203 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551204}
1205
[email protected]1628fe92011-10-04 23:04:551206// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011207TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551208 MockRead data_reads[] = {
1209 MockRead("HTTP/1.1 302 Redirect\r\n"),
1210 MockRead("Location: http://good.com/\r\n"),
1211 MockRead("Location: http://evil.com/\r\n"),
1212 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061213 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551214 };
Ryan Sleevib8d7ea02018-05-07 20:01:011215 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011216 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551217}
1218
[email protected]ef0faf2e72009-03-05 23:27:231219// Do a request using the HEAD method. Verify that we don't try to read the
1220// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011221TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421222 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231223 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231224 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101225 request.traffic_annotation =
1226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231227
danakj1fd259a02016-04-16 03:17:091228 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161229 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091230 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161231 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091232 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1233 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271234
[email protected]ef0faf2e72009-03-05 23:27:231235 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131236 MockWrite("HEAD / HTTP/1.1\r\n"
1237 "Host: www.example.org\r\n"
1238 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231239 };
1240 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231241 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1242 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231243
mmenked39192ee2015-12-09 00:57:231244 // No response body because the test stops reading here.
1245 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231246 };
1247
Ryan Sleevib8d7ea02018-05-07 20:01:011248 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071249 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231250
[email protected]49639fa2011-12-20 23:22:411251 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231252
tfarina42834112016-09-22 13:38:201253 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011254 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231255
1256 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011257 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231258
bnc691fda62016-08-12 00:43:161259 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521260 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231261
1262 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521263 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231264 EXPECT_EQ(1234, response->headers->GetContentLength());
1265 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471266 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091267 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1268 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231269
1270 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101271 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231272 bool has_server_header = response->headers->EnumerateHeader(
1273 &iter, "Server", &server_header);
1274 EXPECT_TRUE(has_server_header);
1275 EXPECT_EQ("Blah", server_header);
1276
1277 // Reading should give EOF right away, since there is no message body
1278 // (despite non-zero content-length).
1279 std::string response_data;
bnc691fda62016-08-12 00:43:161280 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011281 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231282 EXPECT_EQ("", response_data);
1283}
1284
bncd16676a2016-07-20 16:23:011285TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091286 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521287
1288 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351289 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1290 MockRead("hello"),
1291 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1292 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061293 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521294 };
Ryan Sleevib8d7ea02018-05-07 20:01:011295 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071296 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521297
[email protected]0b0bf032010-09-21 18:08:501298 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521299 "hello", "world"
1300 };
1301
1302 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421303 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521304 request.method = "GET";
bncce36dca22015-04-21 22:11:231305 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101306 request.traffic_annotation =
1307 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521308
bnc691fda62016-08-12 00:43:161309 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271310
[email protected]49639fa2011-12-20 23:22:411311 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521312
tfarina42834112016-09-22 13:38:201313 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011314 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521315
1316 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011317 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521318
bnc691fda62016-08-12 00:43:161319 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521320 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521321
wezca1070932016-05-26 20:30:521322 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251323 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471324 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521325
1326 std::string response_data;
bnc691fda62016-08-12 00:43:161327 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011328 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251329 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521330 }
1331}
1332
bncd16676a2016-07-20 16:23:011333TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091334 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221335 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191336 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221337 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271338
[email protected]1c773ea12009-04-28 19:58:421339 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521340 request.method = "POST";
1341 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271342 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101343 request.traffic_annotation =
1344 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521345
shivanishab9a143952016-09-19 17:23:411346 // Check the upload progress returned before initialization is correct.
1347 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1348 EXPECT_EQ(0u, progress.size());
1349 EXPECT_EQ(0u, progress.position());
1350
danakj1fd259a02016-04-16 03:17:091351 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161352 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271353
initial.commit586acc5fe2008-07-26 22:42:521354 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351355 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1356 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1357 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061358 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521359 };
Ryan Sleevib8d7ea02018-05-07 20:01:011360 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071361 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521362
[email protected]49639fa2011-12-20 23:22:411363 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521364
tfarina42834112016-09-22 13:38:201365 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011366 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521367
1368 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011369 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521370
bnc691fda62016-08-12 00:43:161371 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521372 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521373
wezca1070932016-05-26 20:30:521374 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251375 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521376
1377 std::string response_data;
bnc691fda62016-08-12 00:43:161378 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011379 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251380 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521381}
1382
[email protected]3a2d3662009-03-27 03:49:141383// This test is almost the same as Ignores100 above, but the response contains
1384// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571385// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011386TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421387 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141388 request.method = "GET";
1389 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101390 request.traffic_annotation =
1391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141392
danakj1fd259a02016-04-16 03:17:091393 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161394 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271395
[email protected]3a2d3662009-03-27 03:49:141396 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571397 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1398 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141399 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061400 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141401 };
Ryan Sleevib8d7ea02018-05-07 20:01:011402 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071403 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141404
[email protected]49639fa2011-12-20 23:22:411405 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141406
tfarina42834112016-09-22 13:38:201407 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011408 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141409
1410 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011411 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141412
bnc691fda62016-08-12 00:43:161413 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521414 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141415
wezca1070932016-05-26 20:30:521416 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141417 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1418
1419 std::string response_data;
bnc691fda62016-08-12 00:43:161420 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011421 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141422 EXPECT_EQ("hello world", response_data);
1423}
1424
Andrew Comminos517a92c2019-01-14 17:49:561425TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1426 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381427 base::TimeDelta::FromMilliseconds(10);
1428
1429 HttpRequestInfo request;
1430 request.method = "GET";
1431 request.url = GURL("http://www.foo.com/");
1432 request.traffic_annotation =
1433 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1434
1435 std::vector<MockWrite> data_writes = {
1436 MockWrite(ASYNC, 0,
1437 "GET / HTTP/1.1\r\n"
1438 "Host: www.foo.com\r\n"
1439 "Connection: keep-alive\r\n\r\n"),
1440 };
1441
1442 std::vector<MockRead> data_reads = {
1443 // Write one byte of the status line, followed by a pause.
1444 MockRead(ASYNC, 1, "H"),
1445 MockRead(ASYNC, ERR_IO_PENDING, 2),
1446 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1447 MockRead(ASYNC, 4, "hello world"),
1448 MockRead(SYNCHRONOUS, OK, 5),
1449 };
1450
1451 SequencedSocketData data(data_reads, data_writes);
1452 session_deps_.socket_factory->AddSocketDataProvider(&data);
1453
1454 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1455
1456 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1457
1458 TestCompletionCallback callback;
1459
1460 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1462
1463 data.RunUntilPaused();
1464 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561465 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381466 data.Resume();
1467
1468 rv = callback.WaitForResult();
1469 EXPECT_THAT(rv, IsOk());
1470
1471 const HttpResponseInfo* response = trans.GetResponseInfo();
1472 ASSERT_TRUE(response);
1473
1474 EXPECT_TRUE(response->headers);
1475 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1476
1477 LoadTimingInfo load_timing_info;
1478 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1479 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1480 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561481 // Ensure we didn't include the delay in the TTFB time.
1482 EXPECT_EQ(load_timing_info.receive_headers_start,
1483 load_timing_info.connect_timing.connect_end);
1484 // Ensure that the mock clock advanced at all.
1485 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1486 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381487
1488 std::string response_data;
1489 rv = ReadTransaction(&trans, &response_data);
1490 EXPECT_THAT(rv, IsOk());
1491 EXPECT_EQ("hello world", response_data);
1492}
1493
1494// Tests that the time-to-first-byte reported in a transaction's load timing
1495// info uses the first response, even if 1XX/informational.
1496void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561497 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381498 base::TimeDelta::FromMilliseconds(10);
1499
1500 HttpRequestInfo request;
1501 request.method = "GET";
1502 request.url = GURL("https://www.foo.com/");
1503 request.traffic_annotation =
1504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1505
1506 SSLSocketDataProvider ssl(ASYNC, OK);
1507 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1508
1509 std::vector<MockWrite> data_writes;
1510 std::vector<MockRead> data_reads;
1511
1512 spdy::SpdySerializedFrame spdy_req(
1513 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1514
1515 spdy::SpdyHeaderBlock spdy_resp1_headers;
1516 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1517 spdy::SpdySerializedFrame spdy_resp1(
1518 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1519 spdy::SpdySerializedFrame spdy_resp2(
1520 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1521 spdy::SpdySerializedFrame spdy_data(
1522 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1523
1524 if (use_spdy) {
1525 ssl.next_proto = kProtoHTTP2;
1526
1527 data_writes = {CreateMockWrite(spdy_req, 0)};
1528
1529 data_reads = {
1530 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1531 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1532 MockRead(SYNCHRONOUS, OK, 5),
1533 };
1534 } else {
1535 data_writes = {
1536 MockWrite(ASYNC, 0,
1537 "GET / HTTP/1.1\r\n"
1538 "Host: www.foo.com\r\n"
1539 "Connection: keep-alive\r\n\r\n"),
1540 };
1541
1542 data_reads = {
1543 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1544 MockRead(ASYNC, ERR_IO_PENDING, 2),
1545
1546 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1547 MockRead(ASYNC, 4, "hello world"),
1548 MockRead(SYNCHRONOUS, OK, 5),
1549 };
1550 }
1551
1552 SequencedSocketData data(data_reads, data_writes);
1553 session_deps_.socket_factory->AddSocketDataProvider(&data);
1554
1555 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1556
1557 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1558
1559 TestCompletionCallback callback;
1560
1561 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1563
1564 data.RunUntilPaused();
1565 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1566 // the delay before parsing the 200 response.
1567 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561568 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381569 data.Resume();
1570
1571 rv = callback.WaitForResult();
1572 EXPECT_THAT(rv, IsOk());
1573
1574 const HttpResponseInfo* response = trans.GetResponseInfo();
1575 ASSERT_TRUE(response);
1576
1577 LoadTimingInfo load_timing_info;
1578 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1579 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1580 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561581 // Ensure we didn't include the delay in the TTFB time.
1582 EXPECT_EQ(load_timing_info.receive_headers_start,
1583 load_timing_info.connect_timing.connect_end);
1584 // Ensure that the mock clock advanced at all.
1585 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1586 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381587
1588 std::string response_data;
1589 rv = ReadTransaction(&trans, &response_data);
1590 EXPECT_THAT(rv, IsOk());
1591 EXPECT_EQ("hello world", response_data);
1592}
1593
Andrew Comminos517a92c2019-01-14 17:49:561594TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381595 Check100ResponseTiming(false /* use_spdy */);
1596}
1597
Andrew Comminos517a92c2019-01-14 17:49:561598TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381599 Check100ResponseTiming(true /* use_spdy */);
1600}
1601
bncd16676a2016-07-20 16:23:011602TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081603 HttpRequestInfo request;
1604 request.method = "POST";
1605 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101606 request.traffic_annotation =
1607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081608
danakj1fd259a02016-04-16 03:17:091609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161610 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081611
1612 MockRead data_reads[] = {
1613 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1614 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381615 };
Ryan Sleevib8d7ea02018-05-07 20:01:011616 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081617 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381618
zmo9528c9f42015-08-04 22:12:081619 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381620
tfarina42834112016-09-22 13:38:201621 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011622 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381623
zmo9528c9f42015-08-04 22:12:081624 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011625 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381626
zmo9528c9f42015-08-04 22:12:081627 std::string response_data;
bnc691fda62016-08-12 00:43:161628 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011629 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081630 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381631}
1632
bncd16676a2016-07-20 16:23:011633TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381634 HttpRequestInfo request;
1635 request.method = "POST";
1636 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101637 request.traffic_annotation =
1638 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381639
danakj1fd259a02016-04-16 03:17:091640 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161641 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271642
[email protected]ee9410e72010-01-07 01:42:381643 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061644 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381645 };
Ryan Sleevib8d7ea02018-05-07 20:01:011646 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071647 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381648
[email protected]49639fa2011-12-20 23:22:411649 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381650
tfarina42834112016-09-22 13:38:201651 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011652 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381653
1654 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011655 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381656}
1657
[email protected]23e482282013-06-14 16:08:021658void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511659 const MockWrite* write_failure,
1660 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421661 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521662 request.method = "GET";
1663 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101664 request.traffic_annotation =
1665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521666
vishal.b62985ca92015-04-17 08:45:511667 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071668 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271670
[email protected]202965992011-12-07 23:04:511671 // Written data for successfully sending both requests.
1672 MockWrite data1_writes[] = {
1673 MockWrite("GET / HTTP/1.1\r\n"
1674 "Host: www.foo.com\r\n"
1675 "Connection: keep-alive\r\n\r\n"),
1676 MockWrite("GET / HTTP/1.1\r\n"
1677 "Host: www.foo.com\r\n"
1678 "Connection: keep-alive\r\n\r\n")
1679 };
1680
1681 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521682 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351683 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1684 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061685 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521686 };
[email protected]202965992011-12-07 23:04:511687
1688 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491689 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511690 data1_writes[1] = *write_failure;
1691 } else {
1692 ASSERT_TRUE(read_failure);
1693 data1_reads[2] = *read_failure;
1694 }
1695
Ryan Sleevib8d7ea02018-05-07 20:01:011696 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071697 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521698
1699 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351700 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1701 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061702 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521703 };
Ryan Sleevib8d7ea02018-05-07 20:01:011704 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071705 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521706
thestig9d3bb0c2015-01-24 00:49:511707 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521708 "hello", "world"
1709 };
1710
mikecironef22f9812016-10-04 03:40:191711 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521712 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411713 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521714
bnc691fda62016-08-12 00:43:161715 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521716
tfarina42834112016-09-22 13:38:201717 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011718 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521719
1720 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011721 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521722
[email protected]58e32bb2013-01-21 18:23:251723 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161724 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251725 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1726 if (i == 0) {
1727 first_socket_log_id = load_timing_info.socket_log_id;
1728 } else {
1729 // The second request should be using a new socket.
1730 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1731 }
1732
bnc691fda62016-08-12 00:43:161733 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521734 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521735
wezca1070932016-05-26 20:30:521736 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471737 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251738 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521739
1740 std::string response_data;
bnc691fda62016-08-12 00:43:161741 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011742 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251743 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521744 }
1745}
[email protected]3d2a59b2008-09-26 19:44:251746
[email protected]a34f61ee2014-03-18 20:59:491747void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1748 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101749 const MockRead* read_failure,
1750 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491751 HttpRequestInfo request;
1752 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101753 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101754 request.traffic_annotation =
1755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491756
vishal.b62985ca92015-04-17 08:45:511757 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491758 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091759 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491760
[email protected]09356c652014-03-25 15:36:101761 SSLSocketDataProvider ssl1(ASYNC, OK);
1762 SSLSocketDataProvider ssl2(ASYNC, OK);
1763 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361764 ssl1.next_proto = kProtoHTTP2;
1765 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101766 }
1767 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491769
[email protected]09356c652014-03-25 15:36:101770 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131771 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491772 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131773 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351774 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131775 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191776 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491777
[email protected]09356c652014-03-25 15:36:101778 // HTTP/1.1 versions of the request and response.
1779 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1780 "Host: www.foo.com\r\n"
1781 "Connection: keep-alive\r\n\r\n";
1782 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1783 const char kHttpData[] = "hello";
1784
1785 std::vector<MockRead> data1_reads;
1786 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491787 if (write_failure) {
1788 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101789 data1_writes.push_back(*write_failure);
1790 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491791 } else {
1792 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101793 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411794 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101795 } else {
1796 data1_writes.push_back(MockWrite(kHttpRequest));
1797 }
1798 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491799 }
1800
Ryan Sleevib8d7ea02018-05-07 20:01:011801 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491802 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1803
[email protected]09356c652014-03-25 15:36:101804 std::vector<MockRead> data2_reads;
1805 std::vector<MockWrite> data2_writes;
1806
1807 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411808 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101809
bncdf80d44fd2016-07-15 20:27:411810 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1811 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101812 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1813 } else {
1814 data2_writes.push_back(
1815 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1816
1817 data2_reads.push_back(
1818 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1819 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1820 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1821 }
Ryan Sleevib8d7ea02018-05-07 20:01:011822 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491823 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1824
1825 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591826 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491827 // Wait for the preconnect to complete.
1828 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1829 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231830 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491831
1832 // Make the request.
1833 TestCompletionCallback callback;
1834
bnc691fda62016-08-12 00:43:161835 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491836
tfarina42834112016-09-22 13:38:201837 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491839
1840 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011841 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491842
1843 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161844 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101845 TestLoadTimingNotReused(
1846 load_timing_info,
1847 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491848
bnc691fda62016-08-12 00:43:161849 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521850 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491851
wezca1070932016-05-26 20:30:521852 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021853 if (response->was_fetched_via_spdy) {
1854 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1855 } else {
1856 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1857 }
[email protected]a34f61ee2014-03-18 20:59:491858
1859 std::string response_data;
bnc691fda62016-08-12 00:43:161860 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011861 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101862 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491863}
1864
Biljith Jayan45a41722017-08-16 18:43:141865// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181866// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141867// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1868TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1869 HttpRequestInfo request;
1870 request.method = "GET";
1871 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101872 request.traffic_annotation =
1873 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141874
1875 // Check whether we give up after the third try.
1876
1877 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131878 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141879 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131880 spdy::SpdySerializedFrame spdy_response_go_away(
1881 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011882 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1883 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141884
1885 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011886 StaticSocketDataProvider data1(data_read1, data_write);
1887 StaticSocketDataProvider data2(data_read1, data_write);
1888 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141889
1890 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1891 AddSSLSocketData();
1892 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1893 AddSSLSocketData();
1894 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1895 AddSSLSocketData();
1896
1897 TestCompletionCallback callback;
1898 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1899 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1900
1901 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1902 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1903
1904 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181905 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141906}
1907
1908TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1909 HttpRequestInfo request;
1910 request.method = "GET";
1911 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101912 request.traffic_annotation =
1913 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141914
1915 // Check whether we try atleast thrice before giving up.
1916
1917 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131918 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141919 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131920 spdy::SpdySerializedFrame spdy_response_go_away(
1921 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011922 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1923 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141924
1925 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131926 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141927 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131928 spdy::SpdySerializedFrame spdy_data(
1929 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141930 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1931 CreateMockRead(spdy_data, 2)};
1932
1933 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011934 StaticSocketDataProvider data1(data_read1, data_write);
1935 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141936 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011937 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141938
1939 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1940 AddSSLSocketData();
1941 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1942 AddSSLSocketData();
1943 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1944 AddSSLSocketData();
1945
1946 TestCompletionCallback callback;
1947 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1948 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1949
1950 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1951 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1952
1953 rv = callback.WaitForResult();
1954 EXPECT_THAT(rv, IsOk());
1955}
1956
bncd16676a2016-07-20 16:23:011957TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061958 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351959 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511960}
1961
bncd16676a2016-07-20 16:23:011962TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061963 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351964 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251965}
1966
bncd16676a2016-07-20 16:23:011967TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061968 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351969 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251970}
1971
[email protected]d58ceea82014-06-04 10:55:541972// Make sure that on a 408 response (Request Timeout), the request is retried,
1973// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011974TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541975 MockRead read_failure(SYNCHRONOUS,
1976 "HTTP/1.1 408 Request Timeout\r\n"
1977 "Connection: Keep-Alive\r\n"
1978 "Content-Length: 6\r\n\r\n"
1979 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351980 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541981}
1982
bncd16676a2016-07-20 16:23:011983TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491984 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351985 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491986}
1987
bncd16676a2016-07-20 16:23:011988TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491989 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351990 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491991}
1992
bncd16676a2016-07-20 16:23:011993TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491994 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351995 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101996}
1997
bncd16676a2016-07-20 16:23:011998TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101999 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352000 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102001}
2002
[email protected]d58ceea82014-06-04 10:55:542003// Make sure that on a 408 response (Request Timeout), the request is retried,
2004// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012005TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542006 MockRead read_failure(SYNCHRONOUS,
2007 "HTTP/1.1 408 Request Timeout\r\n"
2008 "Connection: Keep-Alive\r\n"
2009 "Content-Length: 6\r\n\r\n"
2010 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352011 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2012 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:542013}
2014
bncd16676a2016-07-20 16:23:012015TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102016 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352017 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:102018}
2019
bncd16676a2016-07-20 16:23:012020TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102021 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352022 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102023}
2024
bncd16676a2016-07-20 16:23:012025TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102026 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352027 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102028}
2029
bncd16676a2016-07-20 16:23:012030TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102031 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352032 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:492033}
2034
bncd16676a2016-07-20 16:23:012035TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422036 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252037 request.method = "GET";
bncce36dca22015-04-21 22:11:232038 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102039 request.traffic_annotation =
2040 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252041
danakj1fd259a02016-04-16 03:17:092042 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162043 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272044
[email protected]3d2a59b2008-09-26 19:44:252045 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062046 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352047 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2048 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062049 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252050 };
Ryan Sleevib8d7ea02018-05-07 20:01:012051 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072052 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252053
[email protected]49639fa2011-12-20 23:22:412054 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252055
tfarina42834112016-09-22 13:38:202056 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012057 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252058
2059 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012060 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592061
2062 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162063 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592064 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252065}
2066
2067// What do various browsers do when the server closes a non-keepalive
2068// connection without sending any response header or body?
2069//
2070// IE7: error page
2071// Safari 3.1.2 (Windows): error page
2072// Firefox 3.0.1: blank page
2073// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422074// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2075// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012076TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252077 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062078 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352079 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2080 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062081 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252082 };
Ryan Sleevib8d7ea02018-05-07 20:01:012083 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012084 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252085}
[email protected]1826a402014-01-08 15:40:482086
[email protected]7a5378b2012-11-04 03:25:172087// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2088// tests. There was a bug causing HttpNetworkTransaction to hang in the
2089// destructor in such situations.
2090// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012091TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172092 HttpRequestInfo request;
2093 request.method = "GET";
bncce36dca22015-04-21 22:11:232094 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102095 request.traffic_annotation =
2096 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172097
danakj1fd259a02016-04-16 03:17:092098 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582099 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192100 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172101
2102 MockRead data_reads[] = {
2103 MockRead("HTTP/1.0 200 OK\r\n"),
2104 MockRead("Connection: keep-alive\r\n"),
2105 MockRead("Content-Length: 100\r\n\r\n"),
2106 MockRead("hello"),
2107 MockRead(SYNCHRONOUS, 0),
2108 };
Ryan Sleevib8d7ea02018-05-07 20:01:012109 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072110 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172111
2112 TestCompletionCallback callback;
2113
tfarina42834112016-09-22 13:38:202114 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012115 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172116
2117 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012118 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172119
Victor Costan9c7302b2018-08-27 16:39:442120 scoped_refptr<IOBufferWithSize> io_buf =
2121 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502122 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172123 if (rv == ERR_IO_PENDING)
2124 rv = callback.WaitForResult();
2125 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502126 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012127 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172128
2129 trans.reset();
fdoray92e35a72016-06-10 15:54:552130 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172131 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2132}
2133
bncd16676a2016-07-20 16:23:012134TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172135 HttpRequestInfo request;
2136 request.method = "GET";
bncce36dca22015-04-21 22:11:232137 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102138 request.traffic_annotation =
2139 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172140
danakj1fd259a02016-04-16 03:17:092141 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582142 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192143 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172144
2145 MockRead data_reads[] = {
2146 MockRead("HTTP/1.0 200 OK\r\n"),
2147 MockRead("Connection: keep-alive\r\n"),
2148 MockRead("Content-Length: 100\r\n\r\n"),
2149 MockRead(SYNCHRONOUS, 0),
2150 };
Ryan Sleevib8d7ea02018-05-07 20:01:012151 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072152 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172153
2154 TestCompletionCallback callback;
2155
tfarina42834112016-09-22 13:38:202156 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012157 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172158
2159 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012160 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172161
Victor Costan9c7302b2018-08-27 16:39:442162 scoped_refptr<IOBufferWithSize> io_buf(
2163 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502164 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172165 if (rv == ERR_IO_PENDING)
2166 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012167 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172168
2169 trans.reset();
fdoray92e35a72016-06-10 15:54:552170 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172171 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2172}
2173
[email protected]0b0bf032010-09-21 18:08:502174// Test that we correctly reuse a keep-alive connection after not explicitly
2175// reading the body.
bncd16676a2016-07-20 16:23:012176TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132177 HttpRequestInfo request;
2178 request.method = "GET";
2179 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102180 request.traffic_annotation =
2181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132182
vishal.b62985ca92015-04-17 08:45:512183 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072184 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092185 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272186
mmenkecc2298e2015-12-07 18:20:182187 const char* request_data =
2188 "GET / HTTP/1.1\r\n"
2189 "Host: www.foo.com\r\n"
2190 "Connection: keep-alive\r\n\r\n";
2191 MockWrite data_writes[] = {
2192 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2193 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2194 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2195 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2196 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2197 };
2198
[email protected]0b0bf032010-09-21 18:08:502199 // Note that because all these reads happen in the same
2200 // StaticSocketDataProvider, it shows that the same socket is being reused for
2201 // all transactions.
mmenkecc2298e2015-12-07 18:20:182202 MockRead data_reads[] = {
2203 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2204 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2205 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2206 MockRead(ASYNC, 7,
2207 "HTTP/1.1 302 Found\r\n"
2208 "Content-Length: 0\r\n\r\n"),
2209 MockRead(ASYNC, 9,
2210 "HTTP/1.1 302 Found\r\n"
2211 "Content-Length: 5\r\n\r\n"
2212 "hello"),
2213 MockRead(ASYNC, 11,
2214 "HTTP/1.1 301 Moved Permanently\r\n"
2215 "Content-Length: 0\r\n\r\n"),
2216 MockRead(ASYNC, 13,
2217 "HTTP/1.1 301 Moved Permanently\r\n"
2218 "Content-Length: 5\r\n\r\n"
2219 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132220
mmenkecc2298e2015-12-07 18:20:182221 // In the next two rounds, IsConnectedAndIdle returns false, due to
2222 // the set_busy_before_sync_reads(true) call, while the
2223 // HttpNetworkTransaction is being shut down, but the socket is still
2224 // reuseable. See http://crbug.com/544255.
2225 MockRead(ASYNC, 15,
2226 "HTTP/1.1 200 Hunky-Dory\r\n"
2227 "Content-Length: 5\r\n\r\n"),
2228 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132229
mmenkecc2298e2015-12-07 18:20:182230 MockRead(ASYNC, 18,
2231 "HTTP/1.1 200 Hunky-Dory\r\n"
2232 "Content-Length: 5\r\n\r\n"
2233 "he"),
2234 MockRead(SYNCHRONOUS, 19, "llo"),
2235
2236 // The body of the final request is actually read.
2237 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2238 MockRead(ASYNC, 22, "hello"),
2239 };
Ryan Sleevib8d7ea02018-05-07 20:01:012240 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182241 data.set_busy_before_sync_reads(true);
2242 session_deps_.socket_factory->AddSocketDataProvider(&data);
2243
Avi Drissman4365a4782018-12-28 19:26:242244 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502245 std::string response_lines[kNumUnreadBodies];
2246
mikecironef22f9812016-10-04 03:40:192247 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182248 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412249 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132250
Jeremy Roman0579ed62017-08-29 15:56:192251 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582252 session.get());
[email protected]fc31d6a42010-06-24 18:05:132253
tfarina42834112016-09-22 13:38:202254 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012255 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132256
[email protected]58e32bb2013-01-21 18:23:252257 LoadTimingInfo load_timing_info;
2258 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2259 if (i == 0) {
2260 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2261 first_socket_log_id = load_timing_info.socket_log_id;
2262 } else {
2263 TestLoadTimingReused(load_timing_info);
2264 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2265 }
2266
[email protected]fc31d6a42010-06-24 18:05:132267 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182268 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132269
mmenkecc2298e2015-12-07 18:20:182270 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502271 response_lines[i] = response->headers->GetStatusLine();
2272
mmenkecc2298e2015-12-07 18:20:182273 // Delete the transaction without reading the response bodies. Then spin
2274 // the message loop, so the response bodies are drained.
2275 trans.reset();
2276 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132277 }
[email protected]0b0bf032010-09-21 18:08:502278
2279 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182280 "HTTP/1.1 204 No Content",
2281 "HTTP/1.1 205 Reset Content",
2282 "HTTP/1.1 304 Not Modified",
2283 "HTTP/1.1 302 Found",
2284 "HTTP/1.1 302 Found",
2285 "HTTP/1.1 301 Moved Permanently",
2286 "HTTP/1.1 301 Moved Permanently",
2287 "HTTP/1.1 200 Hunky-Dory",
2288 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502289 };
2290
Avi Drissman4365a4782018-12-28 19:26:242291 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272292 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502293
2294 for (int i = 0; i < kNumUnreadBodies; ++i)
2295 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2296
[email protected]49639fa2011-12-20 23:22:412297 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162298 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202299 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012300 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162301 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182302 ASSERT_TRUE(response);
2303 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502304 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2305 std::string response_data;
bnc691fda62016-08-12 00:43:162306 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012307 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502308 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132309}
2310
mmenke5f94fda2016-06-02 20:54:132311// Sockets that receive extra data after a response is complete should not be
2312// reused.
bncd16676a2016-07-20 16:23:012313TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132314 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2315 MockWrite data_writes1[] = {
2316 MockWrite("HEAD / HTTP/1.1\r\n"
2317 "Host: www.borked.com\r\n"
2318 "Connection: keep-alive\r\n\r\n"),
2319 };
2320
2321 MockRead data_reads1[] = {
2322 MockRead("HTTP/1.1 200 OK\r\n"
2323 "Connection: keep-alive\r\n"
2324 "Content-Length: 22\r\n\r\n"
2325 "This server is borked."),
2326 };
2327
2328 MockWrite data_writes2[] = {
2329 MockWrite("GET /foo HTTP/1.1\r\n"
2330 "Host: www.borked.com\r\n"
2331 "Connection: keep-alive\r\n\r\n"),
2332 };
2333
2334 MockRead data_reads2[] = {
2335 MockRead("HTTP/1.1 200 OK\r\n"
2336 "Content-Length: 3\r\n\r\n"
2337 "foo"),
2338 };
Ryan Sleevib8d7ea02018-05-07 20:01:012339 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132340 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012341 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132342 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2343
2344 TestCompletionCallback callback;
2345 HttpRequestInfo request1;
2346 request1.method = "HEAD";
2347 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102348 request1.traffic_annotation =
2349 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132350
bnc87dcefc2017-05-25 12:47:582351 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192352 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202353 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012354 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132355
2356 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2357 ASSERT_TRUE(response1);
2358 ASSERT_TRUE(response1->headers);
2359 EXPECT_EQ(200, response1->headers->response_code());
2360 EXPECT_TRUE(response1->headers->IsKeepAlive());
2361
2362 std::string response_data1;
robpercival214763f2016-07-01 23:27:012363 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132364 EXPECT_EQ("", response_data1);
2365 // Deleting the transaction attempts to release the socket back into the
2366 // socket pool.
2367 trans1.reset();
2368
2369 HttpRequestInfo request2;
2370 request2.method = "GET";
2371 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102372 request2.traffic_annotation =
2373 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132374
bnc87dcefc2017-05-25 12:47:582375 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192376 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202377 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012378 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132379
2380 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2381 ASSERT_TRUE(response2);
2382 ASSERT_TRUE(response2->headers);
2383 EXPECT_EQ(200, response2->headers->response_code());
2384
2385 std::string response_data2;
robpercival214763f2016-07-01 23:27:012386 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132387 EXPECT_EQ("foo", response_data2);
2388}
2389
bncd16676a2016-07-20 16:23:012390TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132391 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2392 MockWrite data_writes1[] = {
2393 MockWrite("GET / HTTP/1.1\r\n"
2394 "Host: www.borked.com\r\n"
2395 "Connection: keep-alive\r\n\r\n"),
2396 };
2397
2398 MockRead data_reads1[] = {
2399 MockRead("HTTP/1.1 200 OK\r\n"
2400 "Connection: keep-alive\r\n"
2401 "Content-Length: 22\r\n\r\n"
2402 "This server is borked."
2403 "Bonus data!"),
2404 };
2405
2406 MockWrite data_writes2[] = {
2407 MockWrite("GET /foo HTTP/1.1\r\n"
2408 "Host: www.borked.com\r\n"
2409 "Connection: keep-alive\r\n\r\n"),
2410 };
2411
2412 MockRead data_reads2[] = {
2413 MockRead("HTTP/1.1 200 OK\r\n"
2414 "Content-Length: 3\r\n\r\n"
2415 "foo"),
2416 };
Ryan Sleevib8d7ea02018-05-07 20:01:012417 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012419 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132420 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2421
2422 TestCompletionCallback callback;
2423 HttpRequestInfo request1;
2424 request1.method = "GET";
2425 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102426 request1.traffic_annotation =
2427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132428
bnc87dcefc2017-05-25 12:47:582429 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192430 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202431 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012432 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132433
2434 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2435 ASSERT_TRUE(response1);
2436 ASSERT_TRUE(response1->headers);
2437 EXPECT_EQ(200, response1->headers->response_code());
2438 EXPECT_TRUE(response1->headers->IsKeepAlive());
2439
2440 std::string response_data1;
robpercival214763f2016-07-01 23:27:012441 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132442 EXPECT_EQ("This server is borked.", response_data1);
2443 // Deleting the transaction attempts to release the socket back into the
2444 // socket pool.
2445 trans1.reset();
2446
2447 HttpRequestInfo request2;
2448 request2.method = "GET";
2449 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102450 request2.traffic_annotation =
2451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132452
bnc87dcefc2017-05-25 12:47:582453 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192454 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202455 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012456 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132457
2458 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2459 ASSERT_TRUE(response2);
2460 ASSERT_TRUE(response2->headers);
2461 EXPECT_EQ(200, response2->headers->response_code());
2462
2463 std::string response_data2;
robpercival214763f2016-07-01 23:27:012464 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132465 EXPECT_EQ("foo", response_data2);
2466}
2467
bncd16676a2016-07-20 16:23:012468TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132469 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2470 MockWrite data_writes1[] = {
2471 MockWrite("GET / HTTP/1.1\r\n"
2472 "Host: www.borked.com\r\n"
2473 "Connection: keep-alive\r\n\r\n"),
2474 };
2475
2476 MockRead data_reads1[] = {
2477 MockRead("HTTP/1.1 200 OK\r\n"
2478 "Connection: keep-alive\r\n"
2479 "Transfer-Encoding: chunked\r\n\r\n"),
2480 MockRead("16\r\nThis server is borked.\r\n"),
2481 MockRead("0\r\n\r\nBonus data!"),
2482 };
2483
2484 MockWrite data_writes2[] = {
2485 MockWrite("GET /foo HTTP/1.1\r\n"
2486 "Host: www.borked.com\r\n"
2487 "Connection: keep-alive\r\n\r\n"),
2488 };
2489
2490 MockRead data_reads2[] = {
2491 MockRead("HTTP/1.1 200 OK\r\n"
2492 "Content-Length: 3\r\n\r\n"
2493 "foo"),
2494 };
Ryan Sleevib8d7ea02018-05-07 20:01:012495 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132496 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012497 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132498 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2499
2500 TestCompletionCallback callback;
2501 HttpRequestInfo request1;
2502 request1.method = "GET";
2503 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102504 request1.traffic_annotation =
2505 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132506
bnc87dcefc2017-05-25 12:47:582507 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192508 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202509 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012510 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132511
2512 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2513 ASSERT_TRUE(response1);
2514 ASSERT_TRUE(response1->headers);
2515 EXPECT_EQ(200, response1->headers->response_code());
2516 EXPECT_TRUE(response1->headers->IsKeepAlive());
2517
2518 std::string response_data1;
robpercival214763f2016-07-01 23:27:012519 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132520 EXPECT_EQ("This server is borked.", response_data1);
2521 // Deleting the transaction attempts to release the socket back into the
2522 // socket pool.
2523 trans1.reset();
2524
2525 HttpRequestInfo request2;
2526 request2.method = "GET";
2527 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102528 request2.traffic_annotation =
2529 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132530
bnc87dcefc2017-05-25 12:47:582531 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192532 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202533 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012534 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132535
2536 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2537 ASSERT_TRUE(response2);
2538 ASSERT_TRUE(response2->headers);
2539 EXPECT_EQ(200, response2->headers->response_code());
2540
2541 std::string response_data2;
robpercival214763f2016-07-01 23:27:012542 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132543 EXPECT_EQ("foo", response_data2);
2544}
2545
2546// This is a little different from the others - it tests the case that the
2547// HttpStreamParser doesn't know if there's extra data on a socket or not when
2548// the HttpNetworkTransaction is torn down, because the response body hasn't
2549// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012550TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132551 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2552 MockWrite data_writes1[] = {
2553 MockWrite("GET / HTTP/1.1\r\n"
2554 "Host: www.borked.com\r\n"
2555 "Connection: keep-alive\r\n\r\n"),
2556 };
2557
2558 MockRead data_reads1[] = {
2559 MockRead("HTTP/1.1 200 OK\r\n"
2560 "Connection: keep-alive\r\n"
2561 "Transfer-Encoding: chunked\r\n\r\n"),
2562 MockRead("16\r\nThis server is borked.\r\n"),
2563 MockRead("0\r\n\r\nBonus data!"),
2564 };
Ryan Sleevib8d7ea02018-05-07 20:01:012565 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132566 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2567
2568 TestCompletionCallback callback;
2569 HttpRequestInfo request1;
2570 request1.method = "GET";
2571 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102572 request1.traffic_annotation =
2573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132574
bnc87dcefc2017-05-25 12:47:582575 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192576 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582577 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012578 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132579
bnc87dcefc2017-05-25 12:47:582580 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132581 ASSERT_TRUE(response1);
2582 ASSERT_TRUE(response1->headers);
2583 EXPECT_EQ(200, response1->headers->response_code());
2584 EXPECT_TRUE(response1->headers->IsKeepAlive());
2585
2586 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2587 // response body.
bnc87dcefc2017-05-25 12:47:582588 trans.reset();
mmenke5f94fda2016-06-02 20:54:132589
2590 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2591 // socket can't be reused, rather than returning it to the socket pool.
2592 base::RunLoop().RunUntilIdle();
2593
2594 // There should be no idle sockets in the pool.
2595 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2596}
2597
[email protected]038e9a32008-10-08 22:40:162598// Test the request-challenge-retry sequence for basic auth.
2599// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012600TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422601 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162602 request.method = "GET";
bncce36dca22015-04-21 22:11:232603 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102604 request.traffic_annotation =
2605 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162606
vishal.b62985ca92015-04-17 08:45:512607 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072608 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162610 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272611
[email protected]f9ee6b52008-11-08 06:46:232612 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232613 MockWrite(
2614 "GET / HTTP/1.1\r\n"
2615 "Host: www.example.org\r\n"
2616 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232617 };
2618
[email protected]038e9a32008-10-08 22:40:162619 MockRead data_reads1[] = {
2620 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2621 // Give a couple authenticate options (only the middle one is actually
2622 // supported).
[email protected]22927ad2009-09-21 19:56:192623 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162624 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2625 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2626 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2627 // Large content-length -- won't matter, as connection will be reset.
2628 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062629 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162630 };
2631
2632 // After calling trans->RestartWithAuth(), this is the request we should
2633 // be issuing -- the final header line contains the credentials.
2634 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232635 MockWrite(
2636 "GET / HTTP/1.1\r\n"
2637 "Host: www.example.org\r\n"
2638 "Connection: keep-alive\r\n"
2639 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162640 };
2641
2642 // Lastly, the server responds with the actual content.
2643 MockRead data_reads2[] = {
2644 MockRead("HTTP/1.0 200 OK\r\n"),
2645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2646 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062647 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162648 };
2649
Ryan Sleevib8d7ea02018-05-07 20:01:012650 StaticSocketDataProvider data1(data_reads1, data_writes1);
2651 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072652 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2653 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162654
[email protected]49639fa2011-12-20 23:22:412655 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162656
tfarina42834112016-09-22 13:38:202657 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012658 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162659
2660 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012661 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162662
[email protected]58e32bb2013-01-21 18:23:252663 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162664 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252665 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2666
Ryan Sleevib8d7ea02018-05-07 20:01:012667 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162668 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012669 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162670 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192671
bnc691fda62016-08-12 00:43:162672 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522673 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582674 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162675
[email protected]49639fa2011-12-20 23:22:412676 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162677
bnc691fda62016-08-12 00:43:162678 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012679 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162680
2681 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012682 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162683
[email protected]58e32bb2013-01-21 18:23:252684 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162685 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252686 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2687 // The load timing after restart should have a new socket ID, and times after
2688 // those of the first load timing.
2689 EXPECT_LE(load_timing_info1.receive_headers_end,
2690 load_timing_info2.connect_timing.connect_start);
2691 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2692
Ryan Sleevib8d7ea02018-05-07 20:01:012693 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162694 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012695 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162696 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192697
bnc691fda62016-08-12 00:43:162698 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522699 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582700 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162701 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162702}
2703
ttuttled9dbc652015-09-29 20:00:592704// Test the request-challenge-retry sequence for basic auth.
2705// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012706TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592707 HttpRequestInfo request;
2708 request.method = "GET";
2709 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102710 request.traffic_annotation =
2711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592712
2713 TestNetLog log;
2714 MockHostResolver* resolver = new MockHostResolver();
2715 session_deps_.net_log = &log;
2716 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092717 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162718 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592719
2720 resolver->rules()->ClearRules();
2721 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2722
2723 MockWrite data_writes1[] = {
2724 MockWrite("GET / HTTP/1.1\r\n"
2725 "Host: www.example.org\r\n"
2726 "Connection: keep-alive\r\n\r\n"),
2727 };
2728
2729 MockRead data_reads1[] = {
2730 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2731 // Give a couple authenticate options (only the middle one is actually
2732 // supported).
2733 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2734 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2735 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2736 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2737 // Large content-length -- won't matter, as connection will be reset.
2738 MockRead("Content-Length: 10000\r\n\r\n"),
2739 MockRead(SYNCHRONOUS, ERR_FAILED),
2740 };
2741
2742 // After calling trans->RestartWithAuth(), this is the request we should
2743 // be issuing -- the final header line contains the credentials.
2744 MockWrite data_writes2[] = {
2745 MockWrite("GET / HTTP/1.1\r\n"
2746 "Host: www.example.org\r\n"
2747 "Connection: keep-alive\r\n"
2748 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2749 };
2750
2751 // Lastly, the server responds with the actual content.
2752 MockRead data_reads2[] = {
2753 MockRead("HTTP/1.0 200 OK\r\n"),
2754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2755 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2756 };
2757
Ryan Sleevib8d7ea02018-05-07 20:01:012758 StaticSocketDataProvider data1(data_reads1, data_writes1);
2759 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592760 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2761 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2762
2763 TestCompletionCallback callback1;
2764
bnc691fda62016-08-12 00:43:162765 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202766 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592767
2768 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162769 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592770 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2771
Ryan Sleevib8d7ea02018-05-07 20:01:012772 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162773 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012774 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162775 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592776
bnc691fda62016-08-12 00:43:162777 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592778 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582779 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592780
2781 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162782 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592783 ASSERT_FALSE(endpoint.address().empty());
2784 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2785
2786 resolver->rules()->ClearRules();
2787 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2788
2789 TestCompletionCallback callback2;
2790
bnc691fda62016-08-12 00:43:162791 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592792 AuthCredentials(kFoo, kBar), callback2.callback())));
2793
2794 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162795 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592796 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2797 // The load timing after restart should have a new socket ID, and times after
2798 // those of the first load timing.
2799 EXPECT_LE(load_timing_info1.receive_headers_end,
2800 load_timing_info2.connect_timing.connect_start);
2801 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2802
Ryan Sleevib8d7ea02018-05-07 20:01:012803 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162804 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012805 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162806 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592807
bnc691fda62016-08-12 00:43:162808 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592809 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582810 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592811 EXPECT_EQ(100, response->headers->GetContentLength());
2812
bnc691fda62016-08-12 00:43:162813 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592814 ASSERT_FALSE(endpoint.address().empty());
2815 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2816}
2817
David Benjamin83ddfb32018-03-30 01:07:522818// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2819// will eventually give up.
2820TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2821 HttpRequestInfo request;
2822 request.method = "GET";
2823 request.url = GURL("http://www.example.org/");
2824 request.traffic_annotation =
2825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2826
2827 TestNetLog log;
2828 session_deps_.net_log = &log;
2829 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2830 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2831
2832 MockWrite data_writes[] = {
2833 MockWrite("GET / HTTP/1.1\r\n"
2834 "Host: www.example.org\r\n"
2835 "Connection: keep-alive\r\n\r\n"),
2836 };
2837
2838 MockRead data_reads[] = {
2839 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2840 // Give a couple authenticate options (only the middle one is actually
2841 // supported).
2842 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2843 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2844 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2845 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2846 // Large content-length -- won't matter, as connection will be reset.
2847 MockRead("Content-Length: 10000\r\n\r\n"),
2848 MockRead(SYNCHRONOUS, ERR_FAILED),
2849 };
2850
2851 // After calling trans->RestartWithAuth(), this is the request we should
2852 // be issuing -- the final header line contains the credentials.
2853 MockWrite data_writes_restart[] = {
2854 MockWrite("GET / HTTP/1.1\r\n"
2855 "Host: www.example.org\r\n"
2856 "Connection: keep-alive\r\n"
2857 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2858 };
2859
Ryan Sleevib8d7ea02018-05-07 20:01:012860 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522861 session_deps_.socket_factory->AddSocketDataProvider(&data);
2862
2863 TestCompletionCallback callback;
2864 int rv = callback.GetResult(
2865 trans.Start(&request, callback.callback(), NetLogWithSource()));
2866
2867 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2868 for (int i = 0; i < 32; i++) {
2869 // Check the previous response was a 401.
2870 EXPECT_THAT(rv, IsOk());
2871 const HttpResponseInfo* response = trans.GetResponseInfo();
2872 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582873 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522874
2875 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012876 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522877 session_deps_.socket_factory->AddSocketDataProvider(
2878 data_restarts.back().get());
2879 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2880 callback.callback()));
2881 }
2882
2883 // After too many tries, the transaction should have given up.
2884 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2885}
2886
bncd16676a2016-07-20 16:23:012887TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462888 HttpRequestInfo request;
2889 request.method = "GET";
bncce36dca22015-04-21 22:11:232890 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292891 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102892 request.traffic_annotation =
2893 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462894
danakj1fd259a02016-04-16 03:17:092895 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162896 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272897
[email protected]861fcd52009-08-26 02:33:462898 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232899 MockWrite(
2900 "GET / HTTP/1.1\r\n"
2901 "Host: www.example.org\r\n"
2902 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462903 };
2904
2905 MockRead data_reads[] = {
2906 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2909 // Large content-length -- won't matter, as connection will be reset.
2910 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062911 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462912 };
2913
Ryan Sleevib8d7ea02018-05-07 20:01:012914 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072915 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412916 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462917
tfarina42834112016-09-22 13:38:202918 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462920
2921 rv = callback.WaitForResult();
2922 EXPECT_EQ(0, rv);
2923
Ryan Sleevib8d7ea02018-05-07 20:01:012924 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162925 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012926 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162927 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192928
bnc691fda62016-08-12 00:43:162929 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522930 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582931 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462932}
2933
[email protected]2d2697f92009-02-18 21:00:322934// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2935// connection.
bncd16676a2016-07-20 16:23:012936TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182937 // On the second pass, the body read of the auth challenge is synchronous, so
2938 // IsConnectedAndIdle returns false. The socket should still be drained and
2939 // reused. See http://crbug.com/544255.
2940 for (int i = 0; i < 2; ++i) {
2941 HttpRequestInfo request;
2942 request.method = "GET";
2943 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102944 request.traffic_annotation =
2945 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322946
mmenkecc2298e2015-12-07 18:20:182947 TestNetLog log;
2948 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092949 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272950
mmenkecc2298e2015-12-07 18:20:182951 MockWrite data_writes[] = {
2952 MockWrite(ASYNC, 0,
2953 "GET / HTTP/1.1\r\n"
2954 "Host: www.example.org\r\n"
2955 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322956
bnc691fda62016-08-12 00:43:162957 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182958 // be issuing -- the final header line contains the credentials.
2959 MockWrite(ASYNC, 6,
2960 "GET / HTTP/1.1\r\n"
2961 "Host: www.example.org\r\n"
2962 "Connection: keep-alive\r\n"
2963 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2964 };
[email protected]2d2697f92009-02-18 21:00:322965
mmenkecc2298e2015-12-07 18:20:182966 MockRead data_reads[] = {
2967 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2968 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2969 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2970 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2971 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322972
mmenkecc2298e2015-12-07 18:20:182973 // Lastly, the server responds with the actual content.
2974 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2975 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2976 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2977 MockRead(ASYNC, 10, "Hello"),
2978 };
[email protected]2d2697f92009-02-18 21:00:322979
Ryan Sleevib8d7ea02018-05-07 20:01:012980 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182981 data.set_busy_before_sync_reads(true);
2982 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462983
mmenkecc2298e2015-12-07 18:20:182984 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322985
bnc691fda62016-08-12 00:43:162986 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202987 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012988 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322989
mmenkecc2298e2015-12-07 18:20:182990 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162991 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182992 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322993
bnc691fda62016-08-12 00:43:162994 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182995 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582996 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322997
mmenkecc2298e2015-12-07 18:20:182998 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252999
bnc691fda62016-08-12 00:43:163000 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3001 callback2.callback());
robpercival214763f2016-07-01 23:27:013002 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323003
mmenkecc2298e2015-12-07 18:20:183004 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163005 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183006 TestLoadTimingReused(load_timing_info2);
3007 // The load timing after restart should have the same socket ID, and times
3008 // those of the first load timing.
3009 EXPECT_LE(load_timing_info1.receive_headers_end,
3010 load_timing_info2.send_start);
3011 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323012
bnc691fda62016-08-12 00:43:163013 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183014 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583015 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183016 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323017
mmenkecc2298e2015-12-07 18:20:183018 std::string response_data;
bnc691fda62016-08-12 00:43:163019 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323020
Ryan Sleevib8d7ea02018-05-07 20:01:013021 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163022 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013023 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163024 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183025 }
[email protected]2d2697f92009-02-18 21:00:323026}
3027
3028// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3029// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013030TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423031 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323032 request.method = "GET";
bncce36dca22015-04-21 22:11:233033 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103034 request.traffic_annotation =
3035 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323036
danakj1fd259a02016-04-16 03:17:093037 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273038
[email protected]2d2697f92009-02-18 21:00:323039 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163040 MockWrite("GET / HTTP/1.1\r\n"
3041 "Host: www.example.org\r\n"
3042 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323043
bnc691fda62016-08-12 00:43:163044 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233045 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163046 MockWrite("GET / HTTP/1.1\r\n"
3047 "Host: www.example.org\r\n"
3048 "Connection: keep-alive\r\n"
3049 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323050 };
3051
[email protected]2d2697f92009-02-18 21:00:323052 MockRead data_reads1[] = {
3053 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313055 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323056
3057 // Lastly, the server responds with the actual content.
3058 MockRead("HTTP/1.1 200 OK\r\n"),
3059 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503060 MockRead("Content-Length: 5\r\n\r\n"),
3061 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323062 };
3063
[email protected]2d0a4f92011-05-05 16:38:463064 // An incorrect reconnect would cause this to be read.
3065 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063066 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463067 };
3068
Ryan Sleevib8d7ea02018-05-07 20:01:013069 StaticSocketDataProvider data1(data_reads1, data_writes1);
3070 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073071 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3072 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323073
[email protected]49639fa2011-12-20 23:22:413074 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323075
bnc691fda62016-08-12 00:43:163076 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203077 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013078 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323079
3080 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013081 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323082
bnc691fda62016-08-12 00:43:163083 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523084 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583085 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323086
[email protected]49639fa2011-12-20 23:22:413087 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323088
bnc691fda62016-08-12 00:43:163089 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013090 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323091
3092 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013093 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323094
bnc691fda62016-08-12 00:43:163095 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523096 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583097 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503098 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323099}
3100
3101// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3102// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013103TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423104 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323105 request.method = "GET";
bncce36dca22015-04-21 22:11:233106 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103107 request.traffic_annotation =
3108 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323109
danakj1fd259a02016-04-16 03:17:093110 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273111
[email protected]2d2697f92009-02-18 21:00:323112 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163113 MockWrite("GET / HTTP/1.1\r\n"
3114 "Host: www.example.org\r\n"
3115 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323116
bnc691fda62016-08-12 00:43:163117 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233118 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163119 MockWrite("GET / HTTP/1.1\r\n"
3120 "Host: www.example.org\r\n"
3121 "Connection: keep-alive\r\n"
3122 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323123 };
3124
3125 // Respond with 5 kb of response body.
3126 std::string large_body_string("Unauthorized");
3127 large_body_string.append(5 * 1024, ' ');
3128 large_body_string.append("\r\n");
3129
3130 MockRead data_reads1[] = {
3131 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3132 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3133 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3134 // 5134 = 12 + 5 * 1024 + 2
3135 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063136 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323137
3138 // Lastly, the server responds with the actual content.
3139 MockRead("HTTP/1.1 200 OK\r\n"),
3140 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503141 MockRead("Content-Length: 5\r\n\r\n"),
3142 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323143 };
3144
[email protected]2d0a4f92011-05-05 16:38:463145 // An incorrect reconnect would cause this to be read.
3146 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063147 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463148 };
3149
Ryan Sleevib8d7ea02018-05-07 20:01:013150 StaticSocketDataProvider data1(data_reads1, data_writes1);
3151 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073152 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3153 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323154
[email protected]49639fa2011-12-20 23:22:413155 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323156
bnc691fda62016-08-12 00:43:163157 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203158 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013159 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323160
3161 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013162 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323163
bnc691fda62016-08-12 00:43:163164 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523165 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583166 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323167
[email protected]49639fa2011-12-20 23:22:413168 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323169
bnc691fda62016-08-12 00:43:163170 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013171 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323172
3173 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013174 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323175
bnc691fda62016-08-12 00:43:163176 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523177 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583178 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503179 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323180}
3181
3182// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313183// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013184TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313185 HttpRequestInfo request;
3186 request.method = "GET";
bncce36dca22015-04-21 22:11:233187 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103188 request.traffic_annotation =
3189 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313190
danakj1fd259a02016-04-16 03:17:093191 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273192
[email protected]11203f012009-11-12 23:02:313193 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233194 MockWrite(
3195 "GET / HTTP/1.1\r\n"
3196 "Host: www.example.org\r\n"
3197 "Connection: keep-alive\r\n\r\n"),
3198 // This simulates the seemingly successful write to a closed connection
3199 // if the bug is not fixed.
3200 MockWrite(
3201 "GET / HTTP/1.1\r\n"
3202 "Host: www.example.org\r\n"
3203 "Connection: keep-alive\r\n"
3204 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313205 };
3206
3207 MockRead data_reads1[] = {
3208 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3209 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3210 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3211 MockRead("Content-Length: 14\r\n\r\n"),
3212 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063213 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313214 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063215 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313216 };
3217
bnc691fda62016-08-12 00:43:163218 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313219 // be issuing -- the final header line contains the credentials.
3220 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233221 MockWrite(
3222 "GET / HTTP/1.1\r\n"
3223 "Host: www.example.org\r\n"
3224 "Connection: keep-alive\r\n"
3225 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313226 };
3227
3228 // Lastly, the server responds with the actual content.
3229 MockRead data_reads2[] = {
3230 MockRead("HTTP/1.1 200 OK\r\n"),
3231 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503232 MockRead("Content-Length: 5\r\n\r\n"),
3233 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313234 };
3235
Ryan Sleevib8d7ea02018-05-07 20:01:013236 StaticSocketDataProvider data1(data_reads1, data_writes1);
3237 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073238 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3239 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313240
[email protected]49639fa2011-12-20 23:22:413241 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313242
bnc691fda62016-08-12 00:43:163243 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203244 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313246
3247 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013248 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313249
bnc691fda62016-08-12 00:43:163250 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523251 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583252 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313253
[email protected]49639fa2011-12-20 23:22:413254 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313255
bnc691fda62016-08-12 00:43:163256 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013257 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313258
3259 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013260 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313261
bnc691fda62016-08-12 00:43:163262 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523263 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583264 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503265 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313266}
3267
[email protected]394816e92010-08-03 07:38:593268// Test the request-challenge-retry sequence for basic auth, over a connection
3269// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013270TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013271 HttpRequestInfo request;
3272 request.method = "GET";
bncce36dca22015-04-21 22:11:233273 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013274 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293275 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103276 request.traffic_annotation =
3277 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013278
3279 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593280 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493281 ProxyResolutionService::CreateFixedFromPacResult(
3282 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513283 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013284 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093285 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013286
3287 // Since we have proxy, should try to establish tunnel.
3288 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543289 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173290 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543291 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013292 };
3293
mmenkee71e15332015-10-07 16:39:543294 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013295 // connection.
3296 MockRead data_reads1[] = {
3297 // No credentials.
3298 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3299 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543300 };
ttuttle34f63b52015-03-05 04:33:013301
mmenkee71e15332015-10-07 16:39:543302 // Since the first connection couldn't be reused, need to establish another
3303 // once given credentials.
3304 MockWrite data_writes2[] = {
3305 // After calling trans->RestartWithAuth(), this is the request we should
3306 // be issuing -- the final header line contains the credentials.
3307 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173308 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543309 "Proxy-Connection: keep-alive\r\n"
3310 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3311
3312 MockWrite("GET / HTTP/1.1\r\n"
3313 "Host: www.example.org\r\n"
3314 "Connection: keep-alive\r\n\r\n"),
3315 };
3316
3317 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013318 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3319
3320 MockRead("HTTP/1.1 200 OK\r\n"),
3321 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3322 MockRead("Content-Length: 5\r\n\r\n"),
3323 MockRead(SYNCHRONOUS, "hello"),
3324 };
3325
Ryan Sleevib8d7ea02018-05-07 20:01:013326 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013327 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013328 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543329 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013330 SSLSocketDataProvider ssl(ASYNC, OK);
3331 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3332
3333 TestCompletionCallback callback1;
3334
bnc87dcefc2017-05-25 12:47:583335 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193336 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013337
3338 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013340
3341 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013342 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543343 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013344 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003345 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3346 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013347 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003348 entries, pos,
3349 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3350 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013351
3352 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523353 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013354 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523355 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013356 EXPECT_EQ(407, response->headers->response_code());
3357 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583358 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013359
3360 LoadTimingInfo load_timing_info;
3361 // CONNECT requests and responses are handled at the connect job level, so
3362 // the transaction does not yet have a connection.
3363 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3364
3365 TestCompletionCallback callback2;
3366
3367 rv =
3368 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013369 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013370
3371 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013372 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013373
3374 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523375 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013376
3377 EXPECT_TRUE(response->headers->IsKeepAlive());
3378 EXPECT_EQ(200, response->headers->response_code());
3379 EXPECT_EQ(5, response->headers->GetContentLength());
3380 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3381
3382 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583383 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013384
3385 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3386 TestLoadTimingNotReusedWithPac(load_timing_info,
3387 CONNECT_TIMING_HAS_SSL_TIMES);
3388
3389 trans.reset();
3390 session->CloseAllConnections();
3391}
3392
3393// Test the request-challenge-retry sequence for basic auth, over a connection
3394// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013395TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593396 HttpRequestInfo request;
3397 request.method = "GET";
bncce36dca22015-04-21 22:11:233398 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593399 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293400 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103401 request.traffic_annotation =
3402 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593403
[email protected]cb9bf6ca2011-01-28 13:15:273404 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593405 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493406 ProxyResolutionService::CreateFixedFromPacResult(
3407 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513408 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073409 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093410 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273411
[email protected]394816e92010-08-03 07:38:593412 // Since we have proxy, should try to establish tunnel.
3413 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543414 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173415 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543416 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113417 };
3418
mmenkee71e15332015-10-07 16:39:543419 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083420 // connection.
3421 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543422 // No credentials.
3423 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3424 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3425 MockRead("Proxy-Connection: close\r\n\r\n"),
3426 };
mmenkee0b5c882015-08-26 20:29:113427
mmenkee71e15332015-10-07 16:39:543428 MockWrite data_writes2[] = {
3429 // After calling trans->RestartWithAuth(), this is the request we should
3430 // be issuing -- the final header line contains the credentials.
3431 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173432 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543433 "Proxy-Connection: keep-alive\r\n"
3434 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083435
mmenkee71e15332015-10-07 16:39:543436 MockWrite("GET / HTTP/1.1\r\n"
3437 "Host: www.example.org\r\n"
3438 "Connection: keep-alive\r\n\r\n"),
3439 };
3440
3441 MockRead data_reads2[] = {
3442 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3443
3444 MockRead("HTTP/1.1 200 OK\r\n"),
3445 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3446 MockRead("Content-Length: 5\r\n\r\n"),
3447 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593448 };
3449
Ryan Sleevib8d7ea02018-05-07 20:01:013450 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073451 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013452 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543453 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063454 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073455 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593456
[email protected]49639fa2011-12-20 23:22:413457 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593458
bnc87dcefc2017-05-25 12:47:583459 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193460 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503461
[email protected]49639fa2011-12-20 23:22:413462 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593464
3465 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013466 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543467 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593468 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003469 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3470 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593471 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403472 entries, pos,
mikecirone8b85c432016-09-08 19:11:003473 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3474 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593475
3476 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523477 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013478 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523479 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593480 EXPECT_EQ(407, response->headers->response_code());
3481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583482 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593483
[email protected]029c83b62013-01-24 05:28:203484 LoadTimingInfo load_timing_info;
3485 // CONNECT requests and responses are handled at the connect job level, so
3486 // the transaction does not yet have a connection.
3487 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3488
[email protected]49639fa2011-12-20 23:22:413489 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593490
[email protected]49639fa2011-12-20 23:22:413491 rv = trans->RestartWithAuth(
3492 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013493 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593494
3495 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013496 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593497
3498 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523499 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593500
3501 EXPECT_TRUE(response->headers->IsKeepAlive());
3502 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503503 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593504 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3505
3506 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583507 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503508
[email protected]029c83b62013-01-24 05:28:203509 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3510 TestLoadTimingNotReusedWithPac(load_timing_info,
3511 CONNECT_TIMING_HAS_SSL_TIMES);
3512
[email protected]0b0bf032010-09-21 18:08:503513 trans.reset();
[email protected]102e27c2011-02-23 01:01:313514 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593515}
3516
[email protected]11203f012009-11-12 23:02:313517// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013518// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013519TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233520 // On the second pass, the body read of the auth challenge is synchronous, so
3521 // IsConnectedAndIdle returns false. The socket should still be drained and
3522 // reused. See http://crbug.com/544255.
3523 for (int i = 0; i < 2; ++i) {
3524 HttpRequestInfo request;
3525 request.method = "GET";
3526 request.url = GURL("https://www.example.org/");
3527 // Ensure that proxy authentication is attempted even
3528 // when the no authentication data flag is set.
3529 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103530 request.traffic_annotation =
3531 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013532
mmenked39192ee2015-12-09 00:57:233533 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593534 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493535 ProxyResolutionService::CreateFixed("myproxy:70",
3536 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233537 BoundTestNetLog log;
3538 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093539 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013540
bnc691fda62016-08-12 00:43:163541 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013542
mmenked39192ee2015-12-09 00:57:233543 // Since we have proxy, should try to establish tunnel.
3544 MockWrite data_writes1[] = {
3545 MockWrite(ASYNC, 0,
3546 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3547 "Host: www.example.org:443\r\n"
3548 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013549
bnc691fda62016-08-12 00:43:163550 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233551 // be issuing -- the final header line contains the credentials.
3552 MockWrite(ASYNC, 3,
3553 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3554 "Host: www.example.org:443\r\n"
3555 "Proxy-Connection: keep-alive\r\n"
3556 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3557 };
ttuttle34f63b52015-03-05 04:33:013558
mmenked39192ee2015-12-09 00:57:233559 // The proxy responds to the connect with a 407, using a persistent
3560 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3561 MockRead data_reads1[] = {
3562 // No credentials.
3563 MockRead(ASYNC, 1,
3564 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3565 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3566 "Proxy-Connection: keep-alive\r\n"
3567 "Content-Length: 10\r\n\r\n"),
3568 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013569
mmenked39192ee2015-12-09 00:57:233570 // Wrong credentials (wrong password).
3571 MockRead(ASYNC, 4,
3572 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3573 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3574 "Proxy-Connection: keep-alive\r\n"
3575 "Content-Length: 10\r\n\r\n"),
3576 // No response body because the test stops reading here.
3577 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3578 };
ttuttle34f63b52015-03-05 04:33:013579
Ryan Sleevib8d7ea02018-05-07 20:01:013580 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233581 data1.set_busy_before_sync_reads(true);
3582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013583
mmenked39192ee2015-12-09 00:57:233584 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013585
bnc691fda62016-08-12 00:43:163586 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013587 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013588
Eric Roman79cc7552019-07-19 02:17:543589 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233590 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003591 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3592 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233593 ExpectLogContainsSomewhere(
3594 entries, pos,
mikecirone8b85c432016-09-08 19:11:003595 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3596 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013597
bnc691fda62016-08-12 00:43:163598 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233599 ASSERT_TRUE(response);
3600 ASSERT_TRUE(response->headers);
3601 EXPECT_TRUE(response->headers->IsKeepAlive());
3602 EXPECT_EQ(407, response->headers->response_code());
3603 EXPECT_EQ(10, response->headers->GetContentLength());
3604 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583605 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013606
mmenked39192ee2015-12-09 00:57:233607 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013608
mmenked39192ee2015-12-09 00:57:233609 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163610 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3611 callback2.callback());
robpercival214763f2016-07-01 23:27:013612 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013613
bnc691fda62016-08-12 00:43:163614 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233615 ASSERT_TRUE(response);
3616 ASSERT_TRUE(response->headers);
3617 EXPECT_TRUE(response->headers->IsKeepAlive());
3618 EXPECT_EQ(407, response->headers->response_code());
3619 EXPECT_EQ(10, response->headers->GetContentLength());
3620 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583621 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013622
mmenked39192ee2015-12-09 00:57:233623 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3624 // out of scope.
3625 session->CloseAllConnections();
3626 }
ttuttle34f63b52015-03-05 04:33:013627}
3628
3629// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3630// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013631TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233632 // On the second pass, the body read of the auth challenge is synchronous, so
3633 // IsConnectedAndIdle returns false. The socket should still be drained and
3634 // reused. See http://crbug.com/544255.
3635 for (int i = 0; i < 2; ++i) {
3636 HttpRequestInfo request;
3637 request.method = "GET";
3638 request.url = GURL("https://www.example.org/");
3639 // Ensure that proxy authentication is attempted even
3640 // when the no authentication data flag is set.
3641 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103642 request.traffic_annotation =
3643 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233644
3645 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593646 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493647 ProxyResolutionService::CreateFixed("myproxy:70",
3648 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233649 BoundTestNetLog log;
3650 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093651 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233652
bnc691fda62016-08-12 00:43:163653 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233654
3655 // Since we have proxy, should try to establish tunnel.
3656 MockWrite data_writes1[] = {
3657 MockWrite(ASYNC, 0,
3658 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3659 "Host: www.example.org:443\r\n"
3660 "Proxy-Connection: keep-alive\r\n\r\n"),
3661
bnc691fda62016-08-12 00:43:163662 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233663 // be issuing -- the final header line contains the credentials.
3664 MockWrite(ASYNC, 3,
3665 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3666 "Host: www.example.org:443\r\n"
3667 "Proxy-Connection: keep-alive\r\n"
3668 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3669 };
3670
3671 // The proxy responds to the connect with a 407, using a persistent
3672 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3673 MockRead data_reads1[] = {
3674 // No credentials.
3675 MockRead(ASYNC, 1,
3676 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3677 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3678 "Content-Length: 10\r\n\r\n"),
3679 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3680
3681 // Wrong credentials (wrong password).
3682 MockRead(ASYNC, 4,
3683 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3684 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3685 "Content-Length: 10\r\n\r\n"),
3686 // No response body because the test stops reading here.
3687 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3688 };
3689
Ryan Sleevib8d7ea02018-05-07 20:01:013690 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233691 data1.set_busy_before_sync_reads(true);
3692 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3693
3694 TestCompletionCallback callback1;
3695
bnc691fda62016-08-12 00:43:163696 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013697 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233698
Eric Roman79cc7552019-07-19 02:17:543699 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233700 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003701 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3702 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233703 ExpectLogContainsSomewhere(
3704 entries, pos,
mikecirone8b85c432016-09-08 19:11:003705 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3706 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233707
bnc691fda62016-08-12 00:43:163708 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233709 ASSERT_TRUE(response);
3710 ASSERT_TRUE(response->headers);
3711 EXPECT_TRUE(response->headers->IsKeepAlive());
3712 EXPECT_EQ(407, response->headers->response_code());
3713 EXPECT_EQ(10, response->headers->GetContentLength());
3714 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583715 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503716 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233717
3718 TestCompletionCallback callback2;
3719
3720 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163721 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3722 callback2.callback());
robpercival214763f2016-07-01 23:27:013723 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233724
bnc691fda62016-08-12 00:43:163725 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233726 ASSERT_TRUE(response);
3727 ASSERT_TRUE(response->headers);
3728 EXPECT_TRUE(response->headers->IsKeepAlive());
3729 EXPECT_EQ(407, response->headers->response_code());
3730 EXPECT_EQ(10, response->headers->GetContentLength());
3731 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583732 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503733 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233734
3735 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3736 // out of scope.
3737 session->CloseAllConnections();
3738 }
3739}
3740
3741// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3742// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3743// the case the server sends extra data on the original socket, so it can't be
3744// reused.
bncd16676a2016-07-20 16:23:013745TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273746 HttpRequestInfo request;
3747 request.method = "GET";
bncce36dca22015-04-21 22:11:233748 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273749 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293750 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103751 request.traffic_annotation =
3752 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273753
[email protected]2d2697f92009-02-18 21:00:323754 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593755 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493756 ProxyResolutionService::CreateFixedFromPacResult(
3757 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513758 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073759 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093760 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323761
[email protected]2d2697f92009-02-18 21:00:323762 // Since we have proxy, should try to establish tunnel.
3763 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233764 MockWrite(ASYNC, 0,
3765 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173766 "Host: www.example.org:443\r\n"
3767 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233768 };
[email protected]2d2697f92009-02-18 21:00:323769
mmenked39192ee2015-12-09 00:57:233770 // The proxy responds to the connect with a 407, using a persistent, but sends
3771 // extra data, so the socket cannot be reused.
3772 MockRead data_reads1[] = {
3773 // No credentials.
3774 MockRead(ASYNC, 1,
3775 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3776 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3777 "Content-Length: 10\r\n\r\n"),
3778 MockRead(SYNCHRONOUS, 2, "0123456789"),
3779 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3780 };
3781
3782 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233783 // After calling trans->RestartWithAuth(), this is the request we should
3784 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233785 MockWrite(ASYNC, 0,
3786 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173787 "Host: www.example.org:443\r\n"
3788 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233789 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3790
3791 MockWrite(ASYNC, 2,
3792 "GET / HTTP/1.1\r\n"
3793 "Host: www.example.org\r\n"
3794 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323795 };
3796
mmenked39192ee2015-12-09 00:57:233797 MockRead data_reads2[] = {
3798 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323799
mmenked39192ee2015-12-09 00:57:233800 MockRead(ASYNC, 3,
3801 "HTTP/1.1 200 OK\r\n"
3802 "Content-Type: text/html; charset=iso-8859-1\r\n"
3803 "Content-Length: 5\r\n\r\n"),
3804 // No response body because the test stops reading here.
3805 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323806 };
3807
Ryan Sleevib8d7ea02018-05-07 20:01:013808 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233809 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013811 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233812 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3813 SSLSocketDataProvider ssl(ASYNC, OK);
3814 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323815
[email protected]49639fa2011-12-20 23:22:413816 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323817
bnc87dcefc2017-05-25 12:47:583818 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193819 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323820
mmenked39192ee2015-12-09 00:57:233821 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013822 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233823
Eric Roman79cc7552019-07-19 02:17:543824 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393825 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003826 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3827 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393828 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403829 entries, pos,
mikecirone8b85c432016-09-08 19:11:003830 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3831 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323832
[email protected]1c773ea12009-04-28 19:58:423833 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243834 ASSERT_TRUE(response);
3835 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323836 EXPECT_TRUE(response->headers->IsKeepAlive());
3837 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423838 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583839 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323840
mmenked39192ee2015-12-09 00:57:233841 LoadTimingInfo load_timing_info;
3842 // CONNECT requests and responses are handled at the connect job level, so
3843 // the transaction does not yet have a connection.
3844 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3845
[email protected]49639fa2011-12-20 23:22:413846 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323847
mmenked39192ee2015-12-09 00:57:233848 rv =
3849 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013850 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323851
[email protected]2d2697f92009-02-18 21:00:323852 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233853 EXPECT_EQ(200, response->headers->response_code());
3854 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423855 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133856
mmenked39192ee2015-12-09 00:57:233857 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583858 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233859
3860 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3861 TestLoadTimingNotReusedWithPac(load_timing_info,
3862 CONNECT_TIMING_HAS_SSL_TIMES);
3863
3864 trans.reset();
[email protected]102e27c2011-02-23 01:01:313865 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323866}
3867
mmenkee71e15332015-10-07 16:39:543868// Test the case a proxy closes a socket while the challenge body is being
3869// drained.
bncd16676a2016-07-20 16:23:013870TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543871 HttpRequestInfo request;
3872 request.method = "GET";
3873 request.url = GURL("https://www.example.org/");
3874 // Ensure that proxy authentication is attempted even
3875 // when the no authentication data flag is set.
3876 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103877 request.traffic_annotation =
3878 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543879
3880 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493881 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3882 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093883 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543884
bnc691fda62016-08-12 00:43:163885 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543886
3887 // Since we have proxy, should try to establish tunnel.
3888 MockWrite data_writes1[] = {
3889 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173890 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543891 "Proxy-Connection: keep-alive\r\n\r\n"),
3892 };
3893
3894 // The proxy responds to the connect with a 407, using a persistent
3895 // connection.
3896 MockRead data_reads1[] = {
3897 // No credentials.
3898 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3899 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3900 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3901 // Server hands up in the middle of the body.
3902 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3903 };
3904
3905 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163906 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543907 // be issuing -- the final header line contains the credentials.
3908 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173909 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543910 "Proxy-Connection: keep-alive\r\n"
3911 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3912
3913 MockWrite("GET / HTTP/1.1\r\n"
3914 "Host: www.example.org\r\n"
3915 "Connection: keep-alive\r\n\r\n"),
3916 };
3917
3918 MockRead data_reads2[] = {
3919 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3920
3921 MockRead("HTTP/1.1 200 OK\r\n"),
3922 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3923 MockRead("Content-Length: 5\r\n\r\n"),
3924 MockRead(SYNCHRONOUS, "hello"),
3925 };
3926
Ryan Sleevib8d7ea02018-05-07 20:01:013927 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543928 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013929 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543930 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3931 SSLSocketDataProvider ssl(ASYNC, OK);
3932 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3933
3934 TestCompletionCallback callback;
3935
tfarina42834112016-09-22 13:38:203936 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013937 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543938
bnc691fda62016-08-12 00:43:163939 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543940 ASSERT_TRUE(response);
3941 ASSERT_TRUE(response->headers);
3942 EXPECT_TRUE(response->headers->IsKeepAlive());
3943 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583944 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543945
bnc691fda62016-08-12 00:43:163946 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013947 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543948
bnc691fda62016-08-12 00:43:163949 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543950 ASSERT_TRUE(response);
3951 ASSERT_TRUE(response->headers);
3952 EXPECT_TRUE(response->headers->IsKeepAlive());
3953 EXPECT_EQ(200, response->headers->response_code());
3954 std::string body;
bnc691fda62016-08-12 00:43:163955 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543956 EXPECT_EQ("hello", body);
3957}
3958
[email protected]a8e9b162009-03-12 00:06:443959// Test that we don't read the response body when we fail to establish a tunnel,
3960// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013961TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273962 HttpRequestInfo request;
3963 request.method = "GET";
bncce36dca22015-04-21 22:11:233964 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103965 request.traffic_annotation =
3966 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273967
[email protected]a8e9b162009-03-12 00:06:443968 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493969 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3970 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443971
danakj1fd259a02016-04-16 03:17:093972 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443973
bnc691fda62016-08-12 00:43:163974 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443975
[email protected]a8e9b162009-03-12 00:06:443976 // Since we have proxy, should try to establish tunnel.
3977 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173978 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3979 "Host: www.example.org:443\r\n"
3980 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443981 };
3982
3983 // The proxy responds to the connect with a 407.
3984 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243985 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3986 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3987 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233988 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243989 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443990 };
3991
Ryan Sleevib8d7ea02018-05-07 20:01:013992 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443994
[email protected]49639fa2011-12-20 23:22:413995 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443996
tfarina42834112016-09-22 13:38:203997 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013998 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443999
4000 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014001 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444002
bnc691fda62016-08-12 00:43:164003 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244004 ASSERT_TRUE(response);
4005 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444006 EXPECT_TRUE(response->headers->IsKeepAlive());
4007 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424008 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444009
4010 std::string response_data;
bnc691fda62016-08-12 00:43:164011 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014012 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184013
4014 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:314015 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:444016}
4017
ttuttle7933c112015-01-06 00:55:244018// Test that we don't pass extraneous headers from the proxy's response to the
4019// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014020TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244021 HttpRequestInfo request;
4022 request.method = "GET";
bncce36dca22015-04-21 22:11:234023 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104024 request.traffic_annotation =
4025 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244026
4027 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494028 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4029 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244030
danakj1fd259a02016-04-16 03:17:094031 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244032
bnc691fda62016-08-12 00:43:164033 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244034
4035 // Since we have proxy, should try to establish tunnel.
4036 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174037 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4038 "Host: www.example.org:443\r\n"
4039 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244040 };
4041
4042 // The proxy responds to the connect with a 407.
4043 MockRead data_reads[] = {
4044 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4045 MockRead("X-Foo: bar\r\n"),
4046 MockRead("Set-Cookie: foo=bar\r\n"),
4047 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4048 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234049 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244050 };
4051
Ryan Sleevib8d7ea02018-05-07 20:01:014052 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244053 session_deps_.socket_factory->AddSocketDataProvider(&data);
4054
4055 TestCompletionCallback callback;
4056
tfarina42834112016-09-22 13:38:204057 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014058 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244059
4060 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014061 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244062
bnc691fda62016-08-12 00:43:164063 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244064 ASSERT_TRUE(response);
4065 ASSERT_TRUE(response->headers);
4066 EXPECT_TRUE(response->headers->IsKeepAlive());
4067 EXPECT_EQ(407, response->headers->response_code());
4068 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4069 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4070 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4071
4072 std::string response_data;
bnc691fda62016-08-12 00:43:164073 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014074 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244075
4076 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4077 session->CloseAllConnections();
4078}
4079
[email protected]8fdbcd22010-05-05 02:54:524080// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4081// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014082TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524083 HttpRequestInfo request;
4084 request.method = "GET";
bncce36dca22015-04-21 22:11:234085 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104086 request.traffic_annotation =
4087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524088
[email protected]cb9bf6ca2011-01-28 13:15:274089 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094090 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164091 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274092
[email protected]8fdbcd22010-05-05 02:54:524093 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234094 MockWrite(
4095 "GET / HTTP/1.1\r\n"
4096 "Host: www.example.org\r\n"
4097 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524098 };
4099
4100 MockRead data_reads1[] = {
4101 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4102 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4103 // Large content-length -- won't matter, as connection will be reset.
4104 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064105 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524106 };
4107
Ryan Sleevib8d7ea02018-05-07 20:01:014108 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074109 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524110
[email protected]49639fa2011-12-20 23:22:414111 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524112
tfarina42834112016-09-22 13:38:204113 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014114 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524115
4116 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014117 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524118}
4119
[email protected]7a67a8152010-11-05 18:31:104120// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4121// through a non-authenticating proxy. The request should fail with
4122// ERR_UNEXPECTED_PROXY_AUTH.
4123// Note that it is impossible to detect if an HTTP server returns a 407 through
4124// a non-authenticating proxy - there is nothing to indicate whether the
4125// response came from the proxy or the server, so it is treated as if the proxy
4126// issued the challenge.
bncd16676a2016-07-20 16:23:014127TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274128 HttpRequestInfo request;
4129 request.method = "GET";
bncce36dca22015-04-21 22:11:234130 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104131 request.traffic_annotation =
4132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274133
Ramin Halavatica8d5252018-03-12 05:33:494134 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4135 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514136 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074137 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104139
[email protected]7a67a8152010-11-05 18:31:104140 // Since we have proxy, should try to establish tunnel.
4141 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174142 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4143 "Host: www.example.org:443\r\n"
4144 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104145
rsleevidb16bb02015-11-12 23:47:174146 MockWrite("GET / HTTP/1.1\r\n"
4147 "Host: www.example.org\r\n"
4148 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104149 };
4150
4151 MockRead data_reads1[] = {
4152 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4153
4154 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4155 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4156 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064157 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104158 };
4159
Ryan Sleevib8d7ea02018-05-07 20:01:014160 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074161 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064162 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074163 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104164
[email protected]49639fa2011-12-20 23:22:414165 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104166
bnc691fda62016-08-12 00:43:164167 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104168
bnc691fda62016-08-12 00:43:164169 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014170 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104171
4172 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014173 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544174 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104175 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004176 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4177 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104178 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404179 entries, pos,
mikecirone8b85c432016-09-08 19:11:004180 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4181 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104182}
[email protected]2df19bb2010-08-25 20:13:464183
mmenke2a1781d2015-10-07 19:25:334184// Test a proxy auth scheme that allows default credentials and a proxy server
4185// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014186TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334187 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4188 HttpRequestInfo request;
4189 request.method = "GET";
4190 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104191 request.traffic_annotation =
4192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334193
4194 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594195 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494196 ProxyResolutionService::CreateFixedFromPacResult(
4197 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334198
Jeremy Roman0579ed62017-08-29 15:56:194199 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334200 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194201 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334202 mock_handler->set_allows_default_credentials(true);
4203 auth_handler_factory->AddMockHandler(mock_handler.release(),
4204 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484205 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334206
4207 // Add NetLog just so can verify load timing information gets a NetLog ID.
4208 NetLog net_log;
4209 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094210 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334211
4212 // Since we have proxy, should try to establish tunnel.
4213 MockWrite data_writes1[] = {
4214 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174215 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334216 "Proxy-Connection: keep-alive\r\n\r\n"),
4217 };
4218
4219 // The proxy responds to the connect with a 407, using a non-persistent
4220 // connection.
4221 MockRead data_reads1[] = {
4222 // No credentials.
4223 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4224 MockRead("Proxy-Authenticate: Mock\r\n"),
4225 MockRead("Proxy-Connection: close\r\n\r\n"),
4226 };
4227
4228 // Since the first connection couldn't be reused, need to establish another
4229 // once given credentials.
4230 MockWrite data_writes2[] = {
4231 // After calling trans->RestartWithAuth(), this is the request we should
4232 // be issuing -- the final header line contains the credentials.
4233 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174234 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334235 "Proxy-Connection: keep-alive\r\n"
4236 "Proxy-Authorization: auth_token\r\n\r\n"),
4237
4238 MockWrite("GET / HTTP/1.1\r\n"
4239 "Host: www.example.org\r\n"
4240 "Connection: keep-alive\r\n\r\n"),
4241 };
4242
4243 MockRead data_reads2[] = {
4244 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4245
4246 MockRead("HTTP/1.1 200 OK\r\n"),
4247 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4248 MockRead("Content-Length: 5\r\n\r\n"),
4249 MockRead(SYNCHRONOUS, "hello"),
4250 };
4251
Ryan Sleevib8d7ea02018-05-07 20:01:014252 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334253 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014254 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334255 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4256 SSLSocketDataProvider ssl(ASYNC, OK);
4257 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4258
bnc87dcefc2017-05-25 12:47:584259 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194260 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334261
4262 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204263 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014264 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334265
4266 const HttpResponseInfo* response = trans->GetResponseInfo();
4267 ASSERT_TRUE(response);
4268 ASSERT_TRUE(response->headers);
4269 EXPECT_FALSE(response->headers->IsKeepAlive());
4270 EXPECT_EQ(407, response->headers->response_code());
4271 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4272 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584273 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334274
4275 LoadTimingInfo load_timing_info;
4276 // CONNECT requests and responses are handled at the connect job level, so
4277 // the transaction does not yet have a connection.
4278 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4279
4280 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014281 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334282 response = trans->GetResponseInfo();
4283 ASSERT_TRUE(response);
4284 ASSERT_TRUE(response->headers);
4285 EXPECT_TRUE(response->headers->IsKeepAlive());
4286 EXPECT_EQ(200, response->headers->response_code());
4287 EXPECT_EQ(5, response->headers->GetContentLength());
4288 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4289
4290 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584291 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334292
4293 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4294 TestLoadTimingNotReusedWithPac(load_timing_info,
4295 CONNECT_TIMING_HAS_SSL_TIMES);
4296
4297 trans.reset();
4298 session->CloseAllConnections();
4299}
4300
4301// Test a proxy auth scheme that allows default credentials and a proxy server
4302// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014303TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334304 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4305 HttpRequestInfo request;
4306 request.method = "GET";
4307 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104308 request.traffic_annotation =
4309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334310
4311 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594312 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494313 ProxyResolutionService::CreateFixedFromPacResult(
4314 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334315
Jeremy Roman0579ed62017-08-29 15:56:194316 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334317 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194318 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334319 mock_handler->set_allows_default_credentials(true);
4320 auth_handler_factory->AddMockHandler(mock_handler.release(),
4321 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484322 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334323
4324 // Add NetLog just so can verify load timing information gets a NetLog ID.
4325 NetLog net_log;
4326 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094327 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334328
4329 // Should try to establish tunnel.
4330 MockWrite data_writes1[] = {
4331 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174332 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334333 "Proxy-Connection: keep-alive\r\n\r\n"),
4334
4335 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174336 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334337 "Proxy-Connection: keep-alive\r\n"
4338 "Proxy-Authorization: auth_token\r\n\r\n"),
4339 };
4340
4341 // The proxy responds to the connect with a 407, using a non-persistent
4342 // connection.
4343 MockRead data_reads1[] = {
4344 // No credentials.
4345 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4346 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4347 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4348 };
4349
4350 // Since the first connection was closed, need to establish another once given
4351 // credentials.
4352 MockWrite data_writes2[] = {
4353 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174354 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334355 "Proxy-Connection: keep-alive\r\n"
4356 "Proxy-Authorization: auth_token\r\n\r\n"),
4357
4358 MockWrite("GET / HTTP/1.1\r\n"
4359 "Host: www.example.org\r\n"
4360 "Connection: keep-alive\r\n\r\n"),
4361 };
4362
4363 MockRead data_reads2[] = {
4364 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4365
4366 MockRead("HTTP/1.1 200 OK\r\n"),
4367 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4368 MockRead("Content-Length: 5\r\n\r\n"),
4369 MockRead(SYNCHRONOUS, "hello"),
4370 };
4371
Ryan Sleevib8d7ea02018-05-07 20:01:014372 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334373 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014374 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334375 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4376 SSLSocketDataProvider ssl(ASYNC, OK);
4377 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4378
bnc87dcefc2017-05-25 12:47:584379 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194380 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334381
4382 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204383 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014384 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334385
4386 const HttpResponseInfo* response = trans->GetResponseInfo();
4387 ASSERT_TRUE(response);
4388 ASSERT_TRUE(response->headers);
4389 EXPECT_TRUE(response->headers->IsKeepAlive());
4390 EXPECT_EQ(407, response->headers->response_code());
4391 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4392 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584393 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334394
4395 LoadTimingInfo load_timing_info;
4396 // CONNECT requests and responses are handled at the connect job level, so
4397 // the transaction does not yet have a connection.
4398 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4399
4400 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014401 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334402
4403 response = trans->GetResponseInfo();
4404 ASSERT_TRUE(response);
4405 ASSERT_TRUE(response->headers);
4406 EXPECT_TRUE(response->headers->IsKeepAlive());
4407 EXPECT_EQ(200, response->headers->response_code());
4408 EXPECT_EQ(5, response->headers->GetContentLength());
4409 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4410
4411 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584412 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334413
4414 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4415 TestLoadTimingNotReusedWithPac(load_timing_info,
4416 CONNECT_TIMING_HAS_SSL_TIMES);
4417
4418 trans.reset();
4419 session->CloseAllConnections();
4420}
4421
4422// Test a proxy auth scheme that allows default credentials and a proxy server
4423// that hangs up when credentials are initially sent, and hangs up again when
4424// they are retried.
bncd16676a2016-07-20 16:23:014425TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334426 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4427 HttpRequestInfo request;
4428 request.method = "GET";
4429 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104430 request.traffic_annotation =
4431 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334432
4433 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594434 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494435 ProxyResolutionService::CreateFixedFromPacResult(
4436 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334437
Jeremy Roman0579ed62017-08-29 15:56:194438 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334439 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194440 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334441 mock_handler->set_allows_default_credentials(true);
4442 auth_handler_factory->AddMockHandler(mock_handler.release(),
4443 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484444 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334445
4446 // Add NetLog just so can verify load timing information gets a NetLog ID.
4447 NetLog net_log;
4448 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094449 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334450
4451 // Should try to establish tunnel.
4452 MockWrite data_writes1[] = {
4453 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174454 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334455 "Proxy-Connection: keep-alive\r\n\r\n"),
4456
4457 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174458 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334459 "Proxy-Connection: keep-alive\r\n"
4460 "Proxy-Authorization: auth_token\r\n\r\n"),
4461 };
4462
4463 // The proxy responds to the connect with a 407, and then hangs up after the
4464 // second request is sent.
4465 MockRead data_reads1[] = {
4466 // No credentials.
4467 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4468 MockRead("Content-Length: 0\r\n"),
4469 MockRead("Proxy-Connection: keep-alive\r\n"),
4470 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4471 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4472 };
4473
4474 // HttpNetworkTransaction sees a reused connection that was closed with
4475 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4476 // request.
4477 MockWrite data_writes2[] = {
4478 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174479 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334480 "Proxy-Connection: keep-alive\r\n\r\n"),
4481 };
4482
4483 // The proxy, having had more than enough of us, just hangs up.
4484 MockRead data_reads2[] = {
4485 // No credentials.
4486 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4487 };
4488
Ryan Sleevib8d7ea02018-05-07 20:01:014489 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334490 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014491 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334492 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4493
bnc87dcefc2017-05-25 12:47:584494 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194495 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334496
4497 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204498 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014499 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334500
4501 const HttpResponseInfo* response = trans->GetResponseInfo();
4502 ASSERT_TRUE(response);
4503 ASSERT_TRUE(response->headers);
4504 EXPECT_TRUE(response->headers->IsKeepAlive());
4505 EXPECT_EQ(407, response->headers->response_code());
4506 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4507 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584508 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334509
4510 LoadTimingInfo load_timing_info;
4511 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4512
4513 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014514 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334515
4516 trans.reset();
4517 session->CloseAllConnections();
4518}
4519
Asanka Herathbc3f8f62018-11-16 23:08:304520// This test exercises an odd edge case where the proxy closes the connection
4521// after the authentication handshake is complete. Presumably this technique is
4522// used in lieu of returning a 403 or 5xx status code when the authentication
4523// succeeds, but the user is not authorized to connect to the destination
4524// server. There's no standard for what a proxy should do to indicate a blocked
4525// site.
4526TEST_F(HttpNetworkTransactionTest,
4527 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4528 HttpRequestInfo request;
4529 request.method = "GET";
4530 request.url = GURL("https://www.example.org/");
4531 request.traffic_annotation =
4532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4533
4534 // Configure against proxy server "myproxy:70".
4535 session_deps_.proxy_resolution_service =
4536 ProxyResolutionService::CreateFixedFromPacResult(
4537 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4538
Asanka Herathbc3f8f62018-11-16 23:08:304539 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4540 auth_handler_factory->set_do_init_from_challenge(true);
4541
4542 // Create two mock AuthHandlers. This is because the transaction gets retried
4543 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4544 // was a real network error.
4545 //
4546 // The handlers support both default and explicit credentials. The retry
4547 // mentioned above should be able to reuse the default identity. Thus there
4548 // should never be a need to prompt for explicit credentials.
4549 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4550 mock_handler->set_allows_default_credentials(true);
4551 mock_handler->set_allows_explicit_credentials(true);
4552 mock_handler->set_connection_based(true);
4553 auth_handler_factory->AddMockHandler(mock_handler.release(),
4554 HttpAuth::AUTH_PROXY);
4555 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4556 mock_handler->set_allows_default_credentials(true);
4557 mock_handler->set_allows_explicit_credentials(true);
4558 mock_handler->set_connection_based(true);
4559 auth_handler_factory->AddMockHandler(mock_handler.release(),
4560 HttpAuth::AUTH_PROXY);
4561 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4562
4563 NetLog net_log;
4564 session_deps_.net_log = &net_log;
4565 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4566
4567 // Data for both sockets.
4568 //
4569 // Writes are for the tunnel establishment attempts and the
4570 // authentication handshake.
4571 MockWrite data_writes1[] = {
4572 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4573 "Host: www.example.org:443\r\n"
4574 "Proxy-Connection: keep-alive\r\n\r\n"),
4575
4576 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4577 "Host: www.example.org:443\r\n"
4578 "Proxy-Connection: keep-alive\r\n"
4579 "Proxy-Authorization: auth_token\r\n\r\n"),
4580
4581 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4582 "Host: www.example.org:443\r\n"
4583 "Proxy-Connection: keep-alive\r\n"
4584 "Proxy-Authorization: auth_token\r\n\r\n"),
4585 };
4586
4587 // The server side of the authentication handshake. Note that the response to
4588 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4589 MockRead data_reads1[] = {
4590 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4591 MockRead("Content-Length: 0\r\n"),
4592 MockRead("Proxy-Connection: keep-alive\r\n"),
4593 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4594
4595 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4596 MockRead("Content-Length: 0\r\n"),
4597 MockRead("Proxy-Connection: keep-alive\r\n"),
4598 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4599
4600 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4601 };
4602
4603 StaticSocketDataProvider data1(data_reads1, data_writes1);
4604 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4605
4606 // The second socket is for the reconnection attempt. Data is identical to the
4607 // first attempt.
4608 StaticSocketDataProvider data2(data_reads1, data_writes1);
4609 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4610
4611 auto trans =
4612 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4613
4614 TestCompletionCallback callback;
4615 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4616
4617 // Two rounds per handshake. After one retry, the error is propagated up the
4618 // stack.
4619 for (int i = 0; i < 4; ++i) {
4620 EXPECT_THAT(callback.GetResult(rv), IsOk());
4621
4622 const HttpResponseInfo* response = trans->GetResponseInfo();
4623 ASSERT_TRUE(response);
4624 ASSERT_TRUE(response->headers);
4625 EXPECT_EQ(407, response->headers->response_code());
4626 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4627
4628 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4629 }
4630
4631 // One shall be the number thou shalt retry, and the number of the retrying
4632 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4633 // that thou then proceed to one. Three is right out. Once the number one,
4634 // being the first number, be reached, then lobbest thou thy
4635 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4636 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4637
4638 trans.reset();
4639 session->CloseAllConnections();
4640}
4641
mmenke2a1781d2015-10-07 19:25:334642// Test a proxy auth scheme that allows default credentials and a proxy server
4643// that hangs up when credentials are initially sent, and sends a challenge
4644// again they are retried.
bncd16676a2016-07-20 16:23:014645TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334646 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4647 HttpRequestInfo request;
4648 request.method = "GET";
4649 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104650 request.traffic_annotation =
4651 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334652
4653 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594654 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494655 ProxyResolutionService::CreateFixedFromPacResult(
4656 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334657
Jeremy Roman0579ed62017-08-29 15:56:194658 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334659 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194660 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334661 mock_handler->set_allows_default_credentials(true);
4662 auth_handler_factory->AddMockHandler(mock_handler.release(),
4663 HttpAuth::AUTH_PROXY);
4664 // Add another handler for the second challenge. It supports default
4665 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194666 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334667 mock_handler->set_allows_default_credentials(true);
4668 auth_handler_factory->AddMockHandler(mock_handler.release(),
4669 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484670 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334671
4672 // Add NetLog just so can verify load timing information gets a NetLog ID.
4673 NetLog net_log;
4674 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094675 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334676
4677 // Should try to establish tunnel.
4678 MockWrite data_writes1[] = {
4679 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174680 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334681 "Proxy-Connection: keep-alive\r\n\r\n"),
4682 };
4683
4684 // The proxy responds to the connect with a 407, using a non-persistent
4685 // connection.
4686 MockRead data_reads1[] = {
4687 // No credentials.
4688 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4689 MockRead("Proxy-Authenticate: Mock\r\n"),
4690 MockRead("Proxy-Connection: close\r\n\r\n"),
4691 };
4692
4693 // Since the first connection was closed, need to establish another once given
4694 // credentials.
4695 MockWrite data_writes2[] = {
4696 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174697 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334698 "Proxy-Connection: keep-alive\r\n"
4699 "Proxy-Authorization: auth_token\r\n\r\n"),
4700 };
4701
4702 MockRead data_reads2[] = {
4703 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4704 MockRead("Proxy-Authenticate: Mock\r\n"),
4705 MockRead("Proxy-Connection: close\r\n\r\n"),
4706 };
4707
Ryan Sleevib8d7ea02018-05-07 20:01:014708 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334709 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014710 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334711 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4712 SSLSocketDataProvider ssl(ASYNC, OK);
4713 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4714
bnc87dcefc2017-05-25 12:47:584715 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194716 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334717
4718 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204719 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014720 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334721
4722 const HttpResponseInfo* response = trans->GetResponseInfo();
4723 ASSERT_TRUE(response);
4724 ASSERT_TRUE(response->headers);
4725 EXPECT_EQ(407, response->headers->response_code());
4726 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4727 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584728 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334729
4730 LoadTimingInfo load_timing_info;
4731 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4732
4733 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014734 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334735 response = trans->GetResponseInfo();
4736 ASSERT_TRUE(response);
4737 ASSERT_TRUE(response->headers);
4738 EXPECT_EQ(407, response->headers->response_code());
4739 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584740 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334741
4742 trans.reset();
4743 session->CloseAllConnections();
4744}
4745
asankae2257db2016-10-11 22:03:164746// A more nuanced test than GenerateAuthToken test which asserts that
4747// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4748// unnecessarily invalidated, and that if the server co-operates, the
4749// authentication handshake can continue with the same scheme but with a
4750// different identity.
4751TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4752 HttpRequestInfo request;
4753 request.method = "GET";
4754 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104755 request.traffic_annotation =
4756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164757
Jeremy Roman0579ed62017-08-29 15:56:194758 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164759 auth_handler_factory->set_do_init_from_challenge(true);
4760
4761 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194762 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164763 mock_handler->set_allows_default_credentials(true);
4764 mock_handler->set_allows_explicit_credentials(true);
4765 mock_handler->set_connection_based(true);
4766 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4767 auth_handler_factory->AddMockHandler(mock_handler.release(),
4768 HttpAuth::AUTH_SERVER);
4769
4770 // Add another handler for the second challenge. It supports default
4771 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194772 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164773 mock_handler->set_allows_default_credentials(true);
4774 mock_handler->set_allows_explicit_credentials(true);
4775 mock_handler->set_connection_based(true);
4776 auth_handler_factory->AddMockHandler(mock_handler.release(),
4777 HttpAuth::AUTH_SERVER);
4778 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4779
4780 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4781
4782 MockWrite data_writes1[] = {
4783 MockWrite("GET / HTTP/1.1\r\n"
4784 "Host: www.example.org\r\n"
4785 "Connection: keep-alive\r\n\r\n"),
4786 };
4787
4788 MockRead data_reads1[] = {
4789 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4790 "WWW-Authenticate: Mock\r\n"
4791 "Connection: keep-alive\r\n\r\n"),
4792 };
4793
4794 // Identical to data_writes1[]. The AuthHandler encounters a
4795 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4796 // transaction procceds without an authorization header.
4797 MockWrite data_writes2[] = {
4798 MockWrite("GET / HTTP/1.1\r\n"
4799 "Host: www.example.org\r\n"
4800 "Connection: keep-alive\r\n\r\n"),
4801 };
4802
4803 MockRead data_reads2[] = {
4804 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4805 "WWW-Authenticate: Mock\r\n"
4806 "Connection: keep-alive\r\n\r\n"),
4807 };
4808
4809 MockWrite data_writes3[] = {
4810 MockWrite("GET / HTTP/1.1\r\n"
4811 "Host: www.example.org\r\n"
4812 "Connection: keep-alive\r\n"
4813 "Authorization: auth_token\r\n\r\n"),
4814 };
4815
4816 MockRead data_reads3[] = {
4817 MockRead("HTTP/1.1 200 OK\r\n"
4818 "Content-Length: 5\r\n"
4819 "Content-Type: text/plain\r\n"
4820 "Connection: keep-alive\r\n\r\n"
4821 "Hello"),
4822 };
4823
Ryan Sleevib8d7ea02018-05-07 20:01:014824 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164825 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4826
Ryan Sleevib8d7ea02018-05-07 20:01:014827 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164828 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4829
Ryan Sleevib8d7ea02018-05-07 20:01:014830 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164831 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4832
bnc87dcefc2017-05-25 12:47:584833 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194834 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164835
4836 TestCompletionCallback callback;
4837 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4838 EXPECT_THAT(callback.GetResult(rv), IsOk());
4839
4840 const HttpResponseInfo* response = trans->GetResponseInfo();
4841 ASSERT_TRUE(response);
4842 ASSERT_TRUE(response->headers);
4843 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4844
4845 // The following three tests assert that an authentication challenge was
4846 // received and that the stack is ready to respond to the challenge using
4847 // ambient credentials.
4848 EXPECT_EQ(401, response->headers->response_code());
4849 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584850 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164851
4852 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4853 EXPECT_THAT(callback.GetResult(rv), IsOk());
4854 response = trans->GetResponseInfo();
4855 ASSERT_TRUE(response);
4856 ASSERT_TRUE(response->headers);
4857
4858 // The following three tests assert that an authentication challenge was
4859 // received and that the stack needs explicit credentials before it is ready
4860 // to respond to the challenge.
4861 EXPECT_EQ(401, response->headers->response_code());
4862 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584863 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164864
4865 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4866 EXPECT_THAT(callback.GetResult(rv), IsOk());
4867 response = trans->GetResponseInfo();
4868 ASSERT_TRUE(response);
4869 ASSERT_TRUE(response->headers);
4870 EXPECT_EQ(200, response->headers->response_code());
4871
4872 trans.reset();
4873 session->CloseAllConnections();
4874}
4875
Matt Menked1eb6d42018-01-17 04:54:064876// Proxy resolver that returns a proxy with the same host and port for different
4877// schemes, based on the path of the URL being requests.
4878class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4879 public:
4880 SameProxyWithDifferentSchemesProxyResolver() {}
4881 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4882
4883 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4884
4885 static HostPortPair ProxyHostPortPair() {
4886 return HostPortPair::FromString(ProxyHostPortPairAsString());
4887 }
4888
4889 // ProxyResolver implementation.
4890 int GetProxyForURL(const GURL& url,
4891 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174892 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064893 std::unique_ptr<Request>* request,
4894 const NetLogWithSource& /*net_log*/) override {
4895 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574896 results->set_traffic_annotation(
4897 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064898 if (url.path() == "/socks4") {
4899 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4900 return OK;
4901 }
4902 if (url.path() == "/socks5") {
4903 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4904 return OK;
4905 }
4906 if (url.path() == "/http") {
4907 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4908 return OK;
4909 }
4910 if (url.path() == "/https") {
4911 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4912 return OK;
4913 }
Matt Menkee8648fa2019-01-17 16:47:074914 if (url.path() == "/https_trusted") {
4915 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4916 ProxyHostPortPair(),
4917 true /* is_trusted_proxy */));
4918 return OK;
4919 }
Matt Menked1eb6d42018-01-17 04:54:064920 NOTREACHED();
4921 return ERR_NOT_IMPLEMENTED;
4922 }
4923
4924 private:
4925 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4926};
4927
4928class SameProxyWithDifferentSchemesProxyResolverFactory
4929 : public ProxyResolverFactory {
4930 public:
4931 SameProxyWithDifferentSchemesProxyResolverFactory()
4932 : ProxyResolverFactory(false) {}
4933
Lily Houghton99597862018-03-07 16:40:424934 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4935 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174936 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424937 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064938 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4939 return OK;
4940 }
4941
4942 private:
4943 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4944};
4945
4946// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074947// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064948// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4949// request to foo.com using proxy.com as an HTTP proxy.
4950TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494951 session_deps_.proxy_resolution_service =
4952 std::make_unique<ProxyResolutionService>(
4953 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4954 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4955 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4956 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064957
4958 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4959
4960 MockWrite socks_writes[] = {
4961 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4962 kSOCKS4OkRequestLocalHostPort80Length),
4963 MockWrite(SYNCHRONOUS,
4964 "GET /socks4 HTTP/1.1\r\n"
4965 "Host: test\r\n"
4966 "Connection: keep-alive\r\n\r\n"),
4967 };
4968 MockRead socks_reads[] = {
4969 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4970 MockRead("HTTP/1.0 200 OK\r\n"
4971 "Connection: keep-alive\r\n"
4972 "Content-Length: 15\r\n\r\n"
4973 "SOCKS4 Response"),
4974 };
Ryan Sleevib8d7ea02018-05-07 20:01:014975 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:064976 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
4977
4978 const char kSOCKS5Request[] = {
4979 0x05, // Version
4980 0x01, // Command (CONNECT)
4981 0x00, // Reserved
4982 0x03, // Address type (DOMAINNAME)
4983 0x04, // Length of domain (4)
4984 't', 'e', 's', 't', // Domain string
4985 0x00, 0x50, // 16-bit port (80)
4986 };
4987 MockWrite socks5_writes[] = {
4988 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:244989 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:064990 MockWrite(SYNCHRONOUS,
4991 "GET /socks5 HTTP/1.1\r\n"
4992 "Host: test\r\n"
4993 "Connection: keep-alive\r\n\r\n"),
4994 };
4995 MockRead socks5_reads[] = {
4996 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
4997 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
4998 MockRead("HTTP/1.0 200 OK\r\n"
4999 "Connection: keep-alive\r\n"
5000 "Content-Length: 15\r\n\r\n"
5001 "SOCKS5 Response"),
5002 };
Ryan Sleevib8d7ea02018-05-07 20:01:015003 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065004 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5005
5006 MockWrite http_writes[] = {
5007 MockWrite(SYNCHRONOUS,
5008 "GET http://test/http HTTP/1.1\r\n"
5009 "Host: test\r\n"
5010 "Proxy-Connection: keep-alive\r\n\r\n"),
5011 };
5012 MockRead http_reads[] = {
5013 MockRead("HTTP/1.1 200 OK\r\n"
5014 "Proxy-Connection: keep-alive\r\n"
5015 "Content-Length: 13\r\n\r\n"
5016 "HTTP Response"),
5017 };
Ryan Sleevib8d7ea02018-05-07 20:01:015018 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065019 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5020
5021 MockWrite https_writes[] = {
5022 MockWrite(SYNCHRONOUS,
5023 "GET http://test/https HTTP/1.1\r\n"
5024 "Host: test\r\n"
5025 "Proxy-Connection: keep-alive\r\n\r\n"),
5026 };
5027 MockRead https_reads[] = {
5028 MockRead("HTTP/1.1 200 OK\r\n"
5029 "Proxy-Connection: keep-alive\r\n"
5030 "Content-Length: 14\r\n\r\n"
5031 "HTTPS Response"),
5032 };
Ryan Sleevib8d7ea02018-05-07 20:01:015033 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065034 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5035 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5037
Matt Menkee8648fa2019-01-17 16:47:075038 MockWrite https_trusted_writes[] = {
5039 MockWrite(SYNCHRONOUS,
5040 "GET http://test/https_trusted HTTP/1.1\r\n"
5041 "Host: test\r\n"
5042 "Proxy-Connection: keep-alive\r\n\r\n"),
5043 };
5044 MockRead https_trusted_reads[] = {
5045 MockRead("HTTP/1.1 200 OK\r\n"
5046 "Proxy-Connection: keep-alive\r\n"
5047 "Content-Length: 22\r\n\r\n"
5048 "HTTPS Trusted Response"),
5049 };
5050 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5051 https_trusted_writes);
5052 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5053 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5054 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5055
Matt Menked1eb6d42018-01-17 04:54:065056 struct TestCase {
5057 GURL url;
5058 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075059 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065060 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075061 int expected_idle_socks4_sockets;
5062 int expected_idle_socks5_sockets;
5063 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5064 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065065 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075066 int expected_idle_https_sockets;
5067 // How many idle sockets there should be in the HTTPS proxy socket pool with
5068 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5069 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065070 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075071 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5072 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5073 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5074 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5075 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5076 1},
Matt Menked1eb6d42018-01-17 04:54:065077 };
5078
5079 for (const auto& test_case : kTestCases) {
5080 HttpRequestInfo request;
5081 request.method = "GET";
5082 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105083 request.traffic_annotation =
5084 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065085 std::unique_ptr<HttpNetworkTransaction> trans =
5086 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5087 session.get());
5088 TestCompletionCallback callback;
5089 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5090 EXPECT_THAT(callback.GetResult(rv), IsOk());
5091
5092 const HttpResponseInfo* response = trans->GetResponseInfo();
5093 ASSERT_TRUE(response);
5094 ASSERT_TRUE(response->headers);
5095 EXPECT_EQ(200, response->headers->response_code());
5096 std::string response_data;
5097 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5098 EXPECT_EQ(test_case.expected_response, response_data);
5099
5100 // Return the socket to the socket pool, so can make sure it's not used for
5101 // the next requests.
5102 trans.reset();
5103 base::RunLoop().RunUntilIdle();
5104
5105 // Check the number of idle sockets in the pool, to make sure that used
5106 // sockets are indeed being returned to the socket pool. If each request
5107 // doesn't return an idle socket to the pool, the test would incorrectly
5108 // pass.
Matt Menkee8648fa2019-01-17 16:47:075109 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5110 session
Matt Menked23ab952019-03-06 00:24:405111 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075112 HttpNetworkSession::NORMAL_SOCKET_POOL,
5113 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5114 SameProxyWithDifferentSchemesProxyResolver::
5115 ProxyHostPortPair()))
5116 ->IdleSocketCount());
5117 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5118 session
Matt Menked23ab952019-03-06 00:24:405119 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075120 HttpNetworkSession::NORMAL_SOCKET_POOL,
5121 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5122 SameProxyWithDifferentSchemesProxyResolver::
5123 ProxyHostPortPair()))
5124 ->IdleSocketCount());
5125 EXPECT_EQ(test_case.expected_idle_http_sockets,
5126 session
Matt Menked23ab952019-03-06 00:24:405127 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075128 HttpNetworkSession::NORMAL_SOCKET_POOL,
5129 ProxyServer(ProxyServer::SCHEME_HTTP,
5130 SameProxyWithDifferentSchemesProxyResolver::
5131 ProxyHostPortPair()))
5132 ->IdleSocketCount());
5133 EXPECT_EQ(test_case.expected_idle_https_sockets,
5134 session
Matt Menked23ab952019-03-06 00:24:405135 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075136 HttpNetworkSession::NORMAL_SOCKET_POOL,
5137 ProxyServer(ProxyServer::SCHEME_HTTPS,
5138 SameProxyWithDifferentSchemesProxyResolver::
5139 ProxyHostPortPair()))
5140 ->IdleSocketCount());
5141 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5142 session
Matt Menked23ab952019-03-06 00:24:405143 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075144 HttpNetworkSession::NORMAL_SOCKET_POOL,
5145 ProxyServer(ProxyServer::SCHEME_HTTPS,
5146 SameProxyWithDifferentSchemesProxyResolver::
5147 ProxyHostPortPair(),
5148 true /* is_trusted_proxy */))
5149 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065150 }
5151}
5152
[email protected]029c83b62013-01-24 05:28:205153// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015154TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205155 HttpRequestInfo request1;
5156 request1.method = "GET";
bncce36dca22015-04-21 22:11:235157 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105158 request1.traffic_annotation =
5159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205160
5161 HttpRequestInfo request2;
5162 request2.method = "GET";
bncce36dca22015-04-21 22:11:235163 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105164 request2.traffic_annotation =
5165 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205166
5167 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495168 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5169 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515170 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075171 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095172 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205173
5174 // Since we have proxy, should try to establish tunnel.
5175 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175176 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5177 "Host: www.example.org:443\r\n"
5178 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205179
rsleevidb16bb02015-11-12 23:47:175180 MockWrite("GET /1 HTTP/1.1\r\n"
5181 "Host: www.example.org\r\n"
5182 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205183
rsleevidb16bb02015-11-12 23:47:175184 MockWrite("GET /2 HTTP/1.1\r\n"
5185 "Host: www.example.org\r\n"
5186 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205187 };
5188
5189 // The proxy responds to the connect with a 407, using a persistent
5190 // connection.
5191 MockRead data_reads1[] = {
5192 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5193
5194 MockRead("HTTP/1.1 200 OK\r\n"),
5195 MockRead("Content-Length: 1\r\n\r\n"),
5196 MockRead(SYNCHRONOUS, "1"),
5197
5198 MockRead("HTTP/1.1 200 OK\r\n"),
5199 MockRead("Content-Length: 2\r\n\r\n"),
5200 MockRead(SYNCHRONOUS, "22"),
5201 };
5202
Ryan Sleevib8d7ea02018-05-07 20:01:015203 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075204 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205205 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075206 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205207
5208 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585209 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195210 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205211
5212 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205214
5215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015216 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205217
5218 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525219 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475220 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525221 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205222 EXPECT_EQ(1, response1->headers->GetContentLength());
5223
5224 LoadTimingInfo load_timing_info1;
5225 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5226 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5227
5228 trans1.reset();
5229
5230 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585231 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195232 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205233
5234 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015235 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205236
5237 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015238 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205239
5240 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525241 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475242 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525243 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205244 EXPECT_EQ(2, response2->headers->GetContentLength());
5245
5246 LoadTimingInfo load_timing_info2;
5247 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5248 TestLoadTimingReused(load_timing_info2);
5249
5250 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5251
5252 trans2.reset();
5253 session->CloseAllConnections();
5254}
5255
5256// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015257TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205258 HttpRequestInfo request1;
5259 request1.method = "GET";
bncce36dca22015-04-21 22:11:235260 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105261 request1.traffic_annotation =
5262 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205263
5264 HttpRequestInfo request2;
5265 request2.method = "GET";
bncce36dca22015-04-21 22:11:235266 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105267 request2.traffic_annotation =
5268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205269
5270 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595271 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495272 ProxyResolutionService::CreateFixedFromPacResult(
5273 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515274 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075275 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095276 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205277
5278 // Since we have proxy, should try to establish tunnel.
5279 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175280 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5281 "Host: www.example.org:443\r\n"
5282 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205283
rsleevidb16bb02015-11-12 23:47:175284 MockWrite("GET /1 HTTP/1.1\r\n"
5285 "Host: www.example.org\r\n"
5286 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205287
rsleevidb16bb02015-11-12 23:47:175288 MockWrite("GET /2 HTTP/1.1\r\n"
5289 "Host: www.example.org\r\n"
5290 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205291 };
5292
5293 // The proxy responds to the connect with a 407, using a persistent
5294 // connection.
5295 MockRead data_reads1[] = {
5296 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5297
5298 MockRead("HTTP/1.1 200 OK\r\n"),
5299 MockRead("Content-Length: 1\r\n\r\n"),
5300 MockRead(SYNCHRONOUS, "1"),
5301
5302 MockRead("HTTP/1.1 200 OK\r\n"),
5303 MockRead("Content-Length: 2\r\n\r\n"),
5304 MockRead(SYNCHRONOUS, "22"),
5305 };
5306
Ryan Sleevib8d7ea02018-05-07 20:01:015307 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075308 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205309 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205311
5312 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585313 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195314 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205315
5316 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205318
5319 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015320 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205321
5322 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525323 ASSERT_TRUE(response1);
5324 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205325 EXPECT_EQ(1, response1->headers->GetContentLength());
5326
5327 LoadTimingInfo load_timing_info1;
5328 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5329 TestLoadTimingNotReusedWithPac(load_timing_info1,
5330 CONNECT_TIMING_HAS_SSL_TIMES);
5331
5332 trans1.reset();
5333
5334 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585335 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195336 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205337
5338 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205340
5341 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015342 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205343
5344 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525345 ASSERT_TRUE(response2);
5346 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205347 EXPECT_EQ(2, response2->headers->GetContentLength());
5348
5349 LoadTimingInfo load_timing_info2;
5350 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5351 TestLoadTimingReusedWithPac(load_timing_info2);
5352
5353 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5354
5355 trans2.reset();
5356 session->CloseAllConnections();
5357}
5358
[email protected]2df19bb2010-08-25 20:13:465359// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015360TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275361 HttpRequestInfo request;
5362 request.method = "GET";
bncce36dca22015-04-21 22:11:235363 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105364 request.traffic_annotation =
5365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275366
[email protected]2df19bb2010-08-25 20:13:465367 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495368 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5369 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515370 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075371 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095372 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465373
[email protected]2df19bb2010-08-25 20:13:465374 // Since we have proxy, should use full url
5375 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235376 MockWrite(
5377 "GET http://www.example.org/ HTTP/1.1\r\n"
5378 "Host: www.example.org\r\n"
5379 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465380 };
5381
5382 MockRead data_reads1[] = {
5383 MockRead("HTTP/1.1 200 OK\r\n"),
5384 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5385 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065386 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465387 };
5388
Ryan Sleevib8d7ea02018-05-07 20:01:015389 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075390 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065391 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465393
[email protected]49639fa2011-12-20 23:22:415394 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465395
bnc691fda62016-08-12 00:43:165396 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505397
bnc691fda62016-08-12 00:43:165398 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015399 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465400
5401 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015402 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465403
[email protected]58e32bb2013-01-21 18:23:255404 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165405 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255406 TestLoadTimingNotReused(load_timing_info,
5407 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5408
bnc691fda62016-08-12 00:43:165409 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525410 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465411
tbansal2ecbbc72016-10-06 17:15:475412 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465413 EXPECT_TRUE(response->headers->IsKeepAlive());
5414 EXPECT_EQ(200, response->headers->response_code());
5415 EXPECT_EQ(100, response->headers->GetContentLength());
5416 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5417
5418 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585419 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465420}
5421
[email protected]7642b5ae2010-09-01 20:55:175422// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015423TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275424 HttpRequestInfo request;
5425 request.method = "GET";
bncce36dca22015-04-21 22:11:235426 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105427 request.traffic_annotation =
5428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275429
[email protected]7642b5ae2010-09-01 20:55:175430 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495431 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5432 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515433 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075434 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095435 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175436
bncce36dca22015-04-21 22:11:235437 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135438 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455439 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415440 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175441
Ryan Hamilton0239aac2018-05-19 00:03:135442 spdy::SpdySerializedFrame resp(
5443 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5444 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175445 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415446 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175447 };
5448
Ryan Sleevib8d7ea02018-05-07 20:01:015449 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075450 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175451
[email protected]8ddf8322012-02-23 18:08:065452 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365453 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075454 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175455
[email protected]49639fa2011-12-20 23:22:415456 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175457
bnc691fda62016-08-12 00:43:165458 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505459
bnc691fda62016-08-12 00:43:165460 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175462
5463 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015464 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175465
[email protected]58e32bb2013-01-21 18:23:255466 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165467 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255468 TestLoadTimingNotReused(load_timing_info,
5469 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5470
bnc691fda62016-08-12 00:43:165471 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525472 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475473 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525474 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025475 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175476
5477 std::string response_data;
bnc691fda62016-08-12 00:43:165478 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235479 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175480}
5481
[email protected]1c173852014-06-19 12:51:505482// Verifies that a session which races and wins against the owning transaction
5483// (completing prior to host resolution), doesn't fail the transaction.
5484// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015485TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505486 HttpRequestInfo request;
5487 request.method = "GET";
bncce36dca22015-04-21 22:11:235488 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105489 request.traffic_annotation =
5490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505491
5492 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495493 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5494 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515495 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505496 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505498
bncce36dca22015-04-21 22:11:235499 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135500 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455501 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415502 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505503
Raul Tambre94493c652019-03-11 17:18:355504 spdy::SpdySerializedFrame resp(
5505 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135506 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505507 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415508 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505509 };
5510
Ryan Sleevib8d7ea02018-05-07 20:01:015511 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505512 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5513
5514 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365515 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5517
5518 TestCompletionCallback callback1;
5519
bnc691fda62016-08-12 00:43:165520 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505521
5522 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505523 session_deps_.host_resolver->set_ondemand_mode(true);
5524
bnc691fda62016-08-12 00:43:165525 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505527
5528 // Race a session to the proxy, which completes first.
5529 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045530 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115531 PRIVACY_MODE_DISABLED,
5532 SpdySessionKey::IsProxySession::kTrue, SocketTag());
[email protected]1c173852014-06-19 12:51:505533 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525534 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505535
5536 // Unstall the resolution begun by the transaction.
5537 session_deps_.host_resolver->set_ondemand_mode(true);
5538 session_deps_.host_resolver->ResolveAllPending();
5539
5540 EXPECT_FALSE(callback1.have_result());
5541 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015542 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505543
bnc691fda62016-08-12 00:43:165544 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525545 ASSERT_TRUE(response);
5546 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025547 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505548
5549 std::string response_data;
bnc691fda62016-08-12 00:43:165550 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505551 EXPECT_EQ(kUploadData, response_data);
5552}
5553
[email protected]dc7bd1c52010-11-12 00:01:135554// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015555TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275556 HttpRequestInfo request;
5557 request.method = "GET";
bncce36dca22015-04-21 22:11:235558 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105559 request.traffic_annotation =
5560 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275561
[email protected]79cb5c12011-09-12 13:12:045562 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495563 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5564 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515565 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075566 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095567 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135568
[email protected]dc7bd1c52010-11-12 00:01:135569 // The first request will be a bare GET, the second request will be a
5570 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455571 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135572 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485573 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385574 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135575 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465576 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135577 };
Ryan Hamilton0239aac2018-05-19 00:03:135578 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245579 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485580 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135581 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415582 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135583 };
5584
5585 // The first response is a 407 proxy authentication challenge, and the second
5586 // response will be a 200 response since the second request includes a valid
5587 // Authorization header.
5588 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465589 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135590 };
Ryan Hamilton0239aac2018-05-19 00:03:135591 spdy::SpdySerializedFrame resp_authentication(
5592 spdy_util_.ConstructSpdyReplyError(
5593 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245594 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135595 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415596 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135597 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355598 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135599 spdy::SpdySerializedFrame body_data(
5600 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135601 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415602 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465603 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415604 CreateMockRead(resp_data, 4),
5605 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135606 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135607 };
5608
Ryan Sleevib8d7ea02018-05-07 20:01:015609 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075610 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135611
[email protected]8ddf8322012-02-23 18:08:065612 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365613 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075614 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135615
[email protected]49639fa2011-12-20 23:22:415616 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135617
bnc691fda62016-08-12 00:43:165618 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135619
bnc691fda62016-08-12 00:43:165620 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015621 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135622
5623 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015624 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135625
bnc691fda62016-08-12 00:43:165626 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135627
wezca1070932016-05-26 20:30:525628 ASSERT_TRUE(response);
5629 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135630 EXPECT_EQ(407, response->headers->response_code());
5631 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585632 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135633
[email protected]49639fa2011-12-20 23:22:415634 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135635
bnc691fda62016-08-12 00:43:165636 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135638
5639 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015640 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135641
bnc691fda62016-08-12 00:43:165642 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135643
wezca1070932016-05-26 20:30:525644 ASSERT_TRUE(response_restart);
5645 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135646 EXPECT_EQ(200, response_restart->headers->response_code());
5647 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585648 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135649}
5650
[email protected]d9da5fe2010-10-13 22:37:165651// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015652TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275653 HttpRequestInfo request;
5654 request.method = "GET";
bncce36dca22015-04-21 22:11:235655 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105656 request.traffic_annotation =
5657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275658
[email protected]d9da5fe2010-10-13 22:37:165659 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495660 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5661 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515662 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075663 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095664 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165665
bnc691fda62016-08-12 00:43:165666 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165667
bncce36dca22015-04-21 22:11:235668 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135669 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045670 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5671 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235672 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165673
bncce36dca22015-04-21 22:11:235674 const char get[] =
5675 "GET / HTTP/1.1\r\n"
5676 "Host: www.example.org\r\n"
5677 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135678 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195679 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135680 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355681 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165682 const char resp[] = "HTTP/1.1 200 OK\r\n"
5683 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135684 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195685 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135686 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195687 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135688 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415689 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045690
5691 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415692 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5693 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045694 };
5695
[email protected]d9da5fe2010-10-13 22:37:165696 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415697 CreateMockRead(conn_resp, 1, ASYNC),
5698 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5699 CreateMockRead(wrapped_body, 4, ASYNC),
5700 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135701 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165702 };
5703
Ryan Sleevib8d7ea02018-05-07 20:01:015704 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075705 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165706
[email protected]8ddf8322012-02-23 18:08:065707 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365708 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075709 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065710 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075711 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165712
[email protected]49639fa2011-12-20 23:22:415713 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165714
bnc691fda62016-08-12 00:43:165715 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015716 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165717
5718 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015719 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165720
[email protected]58e32bb2013-01-21 18:23:255721 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165722 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255723 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5724
bnc691fda62016-08-12 00:43:165725 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525726 ASSERT_TRUE(response);
5727 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165728 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5729
5730 std::string response_data;
bnc691fda62016-08-12 00:43:165731 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165732 EXPECT_EQ("1234567890", response_data);
5733}
5734
5735// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015736TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5737 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385738
[email protected]cb9bf6ca2011-01-28 13:15:275739 HttpRequestInfo request;
5740 request.method = "GET";
bncce36dca22015-04-21 22:11:235741 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105742 request.traffic_annotation =
5743 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275744
[email protected]d9da5fe2010-10-13 22:37:165745 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495746 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5747 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515748 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075749 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095750 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165751
bnc691fda62016-08-12 00:43:165752 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165753
bncce36dca22015-04-21 22:11:235754 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135755 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045756 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5757 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235758 // fetch https://www.example.org/ via SPDY
5759 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135760 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495761 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135762 spdy::SpdySerializedFrame wrapped_get(
5763 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5764 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355765 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135766 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355767 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135768 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025769 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135770 spdy::SpdySerializedFrame body(
5771 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5772 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025773 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135774 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415775 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135776 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415777 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045778
5779 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415780 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5781 CreateMockWrite(window_update_get_resp, 6),
5782 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045783 };
5784
[email protected]d9da5fe2010-10-13 22:37:165785 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415786 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095787 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415788 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5789 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135790 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165791 };
5792
Ryan Sleevib8d7ea02018-05-07 20:01:015793 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075794 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165795
[email protected]8ddf8322012-02-23 18:08:065796 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365797 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075798 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065799 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365800 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165802
[email protected]49639fa2011-12-20 23:22:415803 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165804
bnc691fda62016-08-12 00:43:165805 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165807
rch32320842015-05-16 15:57:095808 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555809 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095810 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595811 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165812 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015813 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165814
[email protected]58e32bb2013-01-21 18:23:255815 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165816 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255817 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5818
bnc691fda62016-08-12 00:43:165819 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525820 ASSERT_TRUE(response);
5821 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025822 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165823
5824 std::string response_data;
bnc691fda62016-08-12 00:43:165825 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235826 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165827}
5828
5829// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015830TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275831 HttpRequestInfo request;
5832 request.method = "GET";
bncce36dca22015-04-21 22:11:235833 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105834 request.traffic_annotation =
5835 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275836
[email protected]d9da5fe2010-10-13 22:37:165837 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495838 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5839 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515840 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075841 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095842 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165843
bnc691fda62016-08-12 00:43:165844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165845
bncce36dca22015-04-21 22:11:235846 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135847 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045848 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5849 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135850 spdy::SpdySerializedFrame get(
5851 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165852
5853 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415854 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165855 };
5856
Ryan Hamilton0239aac2018-05-19 00:03:135857 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5858 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165859 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415860 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165861 };
5862
Ryan Sleevib8d7ea02018-05-07 20:01:015863 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075864 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165865
[email protected]8ddf8322012-02-23 18:08:065866 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365867 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075868 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065869 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365870 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075871 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165872
[email protected]49639fa2011-12-20 23:22:415873 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165874
bnc691fda62016-08-12 00:43:165875 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015876 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165877
5878 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015879 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165880
ttuttle960fcbf2016-04-19 13:26:325881 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165882}
5883
Matt Menkecb2cd0982018-12-19 17:54:045884// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245885// is observed, but does exist by the time auth credentials are provided. In
5886// this case, auth and SSL are fully negotated on the second request, but then
5887// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045888TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5889 ProxyConfig proxy_config;
5890 proxy_config.set_auto_detect(true);
5891 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5892
5893 CapturingProxyResolver capturing_proxy_resolver;
5894 capturing_proxy_resolver.set_proxy_server(
5895 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5896 session_deps_.proxy_resolution_service =
5897 std::make_unique<ProxyResolutionService>(
5898 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5899 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5900 std::make_unique<CapturingProxyResolverFactory>(
5901 &capturing_proxy_resolver),
5902 nullptr);
5903
5904 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5905
5906 const char kMyUrl[] = "https://www.example.org/";
5907 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5908 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355909 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045910 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5911
5912 spdy_util_.UpdateWithStreamDestruction(1);
5913 spdy::SpdySerializedFrame get2(
5914 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5915 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355916 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045917 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5918
5919 MockWrite auth_challenge_writes[] = {
5920 MockWrite(ASYNC, 0,
5921 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5922 "Host: www.example.org:443\r\n"
5923 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:245924 MockWrite(ASYNC, 2,
5925 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5926 "Host: www.example.org:443\r\n"
5927 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:045928 };
5929
5930 MockRead auth_challenge_reads[] = {
5931 MockRead(ASYNC, 1,
5932 "HTTP/1.1 407 Authentication Required\r\n"
5933 "Content-Length: 0\r\n"
5934 "Proxy-Connection: close\r\n"
5935 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
5936 };
5937
5938 MockWrite spdy_writes[] = {
5939 MockWrite(ASYNC, 0,
5940 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5941 "Host: www.example.org:443\r\n"
5942 "Proxy-Connection: keep-alive\r\n"
5943 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5944 CreateMockWrite(get, 2),
5945 CreateMockWrite(get2, 5),
5946 };
5947
5948 MockRead spdy_reads[] = {
5949 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5950 CreateMockRead(get_resp, 3, ASYNC),
5951 CreateMockRead(body, 4, ASYNC),
5952 CreateMockRead(get_resp2, 6, ASYNC),
5953 CreateMockRead(body2, 7, ASYNC),
5954
5955 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
5956 };
5957
Matt Menke5062be22019-05-01 17:50:245958 MockWrite auth_response_writes_discarded_socket[] = {
5959 MockWrite(ASYNC, 0,
5960 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5961 "Host: www.example.org:443\r\n"
5962 "Proxy-Connection: keep-alive\r\n"
5963 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5964 };
5965
5966 MockRead auth_response_reads_discarded_socket[] = {
5967 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5968 };
5969
Matt Menkecb2cd0982018-12-19 17:54:045970 SequencedSocketData auth_challenge1(auth_challenge_reads,
5971 auth_challenge_writes);
5972 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5973
5974 SequencedSocketData auth_challenge2(auth_challenge_reads,
5975 auth_challenge_writes);
5976 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
5977
5978 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
5979 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5980
Matt Menke5062be22019-05-01 17:50:245981 SequencedSocketData auth_response_discarded_socket(
5982 auth_response_reads_discarded_socket,
5983 auth_response_writes_discarded_socket);
5984 session_deps_.socket_factory->AddSocketDataProvider(
5985 &auth_response_discarded_socket);
5986
Matt Menkecb2cd0982018-12-19 17:54:045987 SSLSocketDataProvider ssl(ASYNC, OK);
5988 ssl.next_proto = kProtoHTTP2;
5989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5990
Matt Menke5062be22019-05-01 17:50:245991 SSLSocketDataProvider ssl2(ASYNC, OK);
5992 ssl2.next_proto = kProtoHTTP2;
5993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5994
Matt Menkecb2cd0982018-12-19 17:54:045995 TestCompletionCallback callback;
5996 std::string response_data;
5997
5998 // Run first request until an auth challenge is observed.
5999 HttpRequestInfo request1;
6000 request1.method = "GET";
6001 request1.url = GURL(kMyUrl);
6002 request1.traffic_annotation =
6003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6004 HttpNetworkTransaction trans1(LOWEST, session.get());
6005 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6006 EXPECT_THAT(callback.GetResult(rv), IsOk());
6007 const HttpResponseInfo* response = trans1.GetResponseInfo();
6008 ASSERT_TRUE(response);
6009 ASSERT_TRUE(response->headers);
6010 EXPECT_EQ(407, response->headers->response_code());
6011 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586012 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046013
6014 // Run second request until an auth challenge is observed.
6015 HttpRequestInfo request2;
6016 request2.method = "GET";
6017 request2.url = GURL(kMyUrl);
6018 request2.traffic_annotation =
6019 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6020 HttpNetworkTransaction trans2(LOWEST, session.get());
6021 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6022 EXPECT_THAT(callback.GetResult(rv), IsOk());
6023 response = trans2.GetResponseInfo();
6024 ASSERT_TRUE(response);
6025 ASSERT_TRUE(response->headers);
6026 EXPECT_EQ(407, response->headers->response_code());
6027 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586028 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046029
6030 // Now provide credentials for the first request, and wait for it to complete.
6031 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6032 rv = callback.GetResult(rv);
6033 EXPECT_THAT(rv, IsOk());
6034 response = trans1.GetResponseInfo();
6035 ASSERT_TRUE(response);
6036 ASSERT_TRUE(response->headers);
6037 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6038 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6039 EXPECT_EQ(kUploadData, response_data);
6040
6041 // Now provide credentials for the second request. It should notice the
6042 // existing session, and reuse it.
6043 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6044 EXPECT_THAT(callback.GetResult(rv), IsOk());
6045 response = trans2.GetResponseInfo();
6046 ASSERT_TRUE(response);
6047 ASSERT_TRUE(response->headers);
6048 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6049 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6050 EXPECT_EQ(kUploadData, response_data);
6051}
6052
[email protected]f6c63db52013-02-02 00:35:226053// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6054// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016055TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226056 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6057 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496058 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6059 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516060 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076061 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096062 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506063 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226064
6065 HttpRequestInfo request1;
6066 request1.method = "GET";
bncce36dca22015-04-21 22:11:236067 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226068 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106069 request1.traffic_annotation =
6070 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226071
6072 HttpRequestInfo request2;
6073 request2.method = "GET";
bncce36dca22015-04-21 22:11:236074 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226075 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106076 request2.traffic_annotation =
6077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226078
bncce36dca22015-04-21 22:11:236079 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136080 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046081 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6082 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136083 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356084 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226085
bncce36dca22015-04-21 22:11:236086 // Fetch https://www.example.org/ via HTTP.
6087 const char get1[] =
6088 "GET / HTTP/1.1\r\n"
6089 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226090 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136091 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196092 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226093 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6094 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136095 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196096 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136097 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196098 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136099 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416100 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226101
bncce36dca22015-04-21 22:11:236102 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136103 spdy::SpdyHeaderBlock connect2_block;
6104 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6105 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6106 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046107 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6108 false));
[email protected]601e03f12014-04-06 16:26:396109
Ryan Hamilton0239aac2018-05-19 00:03:136110 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356111 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226112
bncce36dca22015-04-21 22:11:236113 // Fetch https://mail.example.org/ via HTTP.
6114 const char get2[] =
6115 "GET / HTTP/1.1\r\n"
6116 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226117 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136118 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196119 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226120 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6121 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136122 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196123 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136124 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196125 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226126
6127 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416128 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6129 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226130 };
6131
6132 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416133 CreateMockRead(conn_resp1, 1, ASYNC),
6134 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6135 CreateMockRead(wrapped_body1, 4, ASYNC),
6136 CreateMockRead(conn_resp2, 6, ASYNC),
6137 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6138 CreateMockRead(wrapped_body2, 9, ASYNC),
6139 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226140 };
6141
Ryan Sleevib8d7ea02018-05-07 20:01:016142 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506143 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226144
6145 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366146 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226148 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226150 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506151 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226152
6153 TestCompletionCallback callback;
6154
bnc691fda62016-08-12 00:43:166155 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206156 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016157 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226158
6159 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166160 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226161 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6162
bnc691fda62016-08-12 00:43:166163 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526164 ASSERT_TRUE(response);
6165 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226166 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6167
6168 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446169 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166170 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506171 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226172
bnc691fda62016-08-12 00:43:166173 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206174 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016175 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226176
6177 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166178 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226179 // Even though the SPDY connection is reused, a new tunnelled connection has
6180 // to be created, so the socket's load timing looks like a fresh connection.
6181 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6182
6183 // The requests should have different IDs, since they each are using their own
6184 // separate stream.
6185 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6186
bnc691fda62016-08-12 00:43:166187 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506188 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226189}
6190
6191// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6192// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016193TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226194 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6195 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496196 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6197 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516198 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076199 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096200 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506201 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226202
6203 HttpRequestInfo request1;
6204 request1.method = "GET";
bncce36dca22015-04-21 22:11:236205 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226206 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106207 request1.traffic_annotation =
6208 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226209
6210 HttpRequestInfo request2;
6211 request2.method = "GET";
bncce36dca22015-04-21 22:11:236212 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226213 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106214 request2.traffic_annotation =
6215 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226216
bncce36dca22015-04-21 22:11:236217 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136218 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046219 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6220 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136221 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356222 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226223
bncce36dca22015-04-21 22:11:236224 // Fetch https://www.example.org/ via HTTP.
6225 const char get1[] =
6226 "GET / HTTP/1.1\r\n"
6227 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226228 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136229 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196230 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226231 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6232 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136233 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196234 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136235 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196236 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136237 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416238 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226239
bncce36dca22015-04-21 22:11:236240 // Fetch https://www.example.org/2 via HTTP.
6241 const char get2[] =
6242 "GET /2 HTTP/1.1\r\n"
6243 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226244 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136245 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196246 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226247 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6248 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136249 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196250 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136251 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196252 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226253
6254 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416255 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6256 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226257 };
6258
6259 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416260 CreateMockRead(conn_resp1, 1, ASYNC),
6261 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466262 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416263 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466264 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416265 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226266 };
6267
Ryan Sleevib8d7ea02018-05-07 20:01:016268 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506269 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226270
6271 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366272 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226274 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506275 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226276
6277 TestCompletionCallback callback;
6278
bnc87dcefc2017-05-25 12:47:586279 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196280 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206281 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226283
6284 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016285 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226286
6287 LoadTimingInfo load_timing_info;
6288 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6289 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6290
6291 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526292 ASSERT_TRUE(response);
6293 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226294 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6295
6296 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446297 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506298 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226299 trans.reset();
6300
bnc87dcefc2017-05-25 12:47:586301 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196302 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206303 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016304 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226305
[email protected]f6c63db52013-02-02 00:35:226306 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016307 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226308
6309 LoadTimingInfo load_timing_info2;
6310 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6311 TestLoadTimingReused(load_timing_info2);
6312
6313 // The requests should have the same ID.
6314 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6315
[email protected]90499482013-06-01 00:39:506316 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226317}
6318
6319// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6320// Proxy to different servers.
bncd16676a2016-07-20 16:23:016321TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226322 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496323 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6324 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516325 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076326 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096327 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506328 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226329
6330 HttpRequestInfo request1;
6331 request1.method = "GET";
bncce36dca22015-04-21 22:11:236332 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226333 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106334 request1.traffic_annotation =
6335 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226336
6337 HttpRequestInfo request2;
6338 request2.method = "GET";
bncce36dca22015-04-21 22:11:236339 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226340 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106341 request2.traffic_annotation =
6342 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226343
bncce36dca22015-04-21 22:11:236344 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136345 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236346 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136347 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156348 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136349 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356350 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136351 spdy::SpdySerializedFrame body1(
6352 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386353 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226354
bncce36dca22015-04-21 22:11:236355 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136356 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236357 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136358 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156359 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136360 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356361 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136362 spdy::SpdySerializedFrame body2(
6363 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226364
6365 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416366 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226367 };
6368
6369 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416370 CreateMockRead(get_resp1, 1, ASYNC),
6371 CreateMockRead(body1, 2, ASYNC),
6372 CreateMockRead(get_resp2, 4, ASYNC),
6373 CreateMockRead(body2, 5, ASYNC),
6374 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226375 };
6376
Ryan Sleevib8d7ea02018-05-07 20:01:016377 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506378 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226379
6380 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366381 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226383
6384 TestCompletionCallback callback;
6385
bnc87dcefc2017-05-25 12:47:586386 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196387 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206388 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016389 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226390
6391 LoadTimingInfo load_timing_info;
6392 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6393 TestLoadTimingNotReused(load_timing_info,
6394 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6395
6396 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526397 ASSERT_TRUE(response);
6398 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026399 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226400
6401 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446402 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506403 rv = trans->Read(buf.get(), 256, callback.callback());
6404 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226405 // Delete the first request, so the second one can reuse the socket.
6406 trans.reset();
6407
bnc691fda62016-08-12 00:43:166408 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206409 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016410 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226411
6412 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166413 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226414 TestLoadTimingReused(load_timing_info2);
6415
6416 // The requests should have the same ID.
6417 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6418
bnc691fda62016-08-12 00:43:166419 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506420 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226421}
6422
Matt Menke2436b2f2018-12-11 18:07:116423// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6424// direct (non-proxied) request to the proxy server are not pooled, as that
6425// would break socket pool isolation.
6426TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6427 ProxyConfig proxy_config;
6428 proxy_config.set_auto_detect(true);
6429 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6430
6431 CapturingProxyResolver capturing_proxy_resolver;
6432 session_deps_.proxy_resolution_service =
6433 std::make_unique<ProxyResolutionService>(
6434 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6435 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6436 std::make_unique<CapturingProxyResolverFactory>(
6437 &capturing_proxy_resolver),
6438 nullptr);
6439
6440 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6441
6442 SpdyTestUtil spdy_util1;
6443 // CONNECT to www.example.org:443 via HTTP/2.
6444 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046445 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6446 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116447 // fetch https://www.example.org/ via HTTP/2.
6448 const char kMyUrl[] = "https://www.example.org/";
6449 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6450 spdy::SpdySerializedFrame wrapped_get(
6451 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6452 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356453 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116454 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356455 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116456 spdy::SpdySerializedFrame wrapped_get_resp(
6457 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6458 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6459 spdy::SpdySerializedFrame wrapped_body(
6460 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6461 spdy::SpdySerializedFrame window_update_get_resp(
6462 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6463 spdy::SpdySerializedFrame window_update_body(
6464 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6465
6466 MockWrite spdy_writes1[] = {
6467 CreateMockWrite(connect, 0),
6468 CreateMockWrite(wrapped_get, 2),
6469 CreateMockWrite(window_update_get_resp, 6),
6470 CreateMockWrite(window_update_body, 7),
6471 };
6472
6473 MockRead spdy_reads1[] = {
6474 CreateMockRead(conn_resp, 1, ASYNC),
6475 MockRead(ASYNC, ERR_IO_PENDING, 3),
6476 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6477 CreateMockRead(wrapped_body, 5, ASYNC),
6478 MockRead(ASYNC, 0, 8),
6479 };
6480
6481 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6482 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6483
6484 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6485 // a new pipe.
6486 SpdyTestUtil spdy_util2;
6487 spdy::SpdySerializedFrame req(
6488 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6489 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6490
6491 spdy::SpdySerializedFrame resp(
6492 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6493 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6494 MockRead spdy_reads2[] = {
6495 CreateMockRead(resp, 1),
6496 CreateMockRead(data, 2),
6497 MockRead(ASYNC, 0, 3),
6498 };
6499 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6500 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6501
6502 SSLSocketDataProvider ssl(ASYNC, OK);
6503 ssl.next_proto = kProtoHTTP2;
6504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6505 SSLSocketDataProvider ssl2(ASYNC, OK);
6506 ssl2.next_proto = kProtoHTTP2;
6507 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6508 SSLSocketDataProvider ssl3(ASYNC, OK);
6509 ssl3.next_proto = kProtoHTTP2;
6510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6511
6512 TestCompletionCallback callback;
6513 std::string response_data;
6514
6515 // Make a request using proxy:70 as a HTTP/2 proxy.
6516 capturing_proxy_resolver.set_proxy_server(
6517 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6518 HttpRequestInfo request1;
6519 request1.method = "GET";
6520 request1.url = GURL("https://www.example.org/");
6521 request1.traffic_annotation =
6522 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6523
6524 HttpNetworkTransaction trans1(LOWEST, session.get());
6525 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6527
6528 // Allow the SpdyProxyClientSocket's write callback to complete.
6529 base::RunLoop().RunUntilIdle();
6530 // Now allow the read of the response to complete.
6531 spdy_data1.Resume();
6532 rv = callback.WaitForResult();
6533 EXPECT_THAT(rv, IsOk());
6534
6535 const HttpResponseInfo* response = trans1.GetResponseInfo();
6536 ASSERT_TRUE(response);
6537 ASSERT_TRUE(response->headers);
6538 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6539
6540 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6541 EXPECT_EQ(kUploadData, response_data);
6542 RunUntilIdle();
6543
6544 // Make a direct HTTP/2 request to proxy:70.
6545 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6546 HttpRequestInfo request2;
6547 request2.method = "GET";
6548 request2.url = GURL("https://proxy:70/");
6549 request2.traffic_annotation =
6550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6551 HttpNetworkTransaction trans2(LOWEST, session.get());
6552 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6553 NetLogWithSource())),
6554 IsOk());
6555 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6556}
6557
6558// Same as above, but reverse request order, since the code to check for an
6559// existing session is different for tunnels and direct connections.
6560TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6561 // Configure against https proxy server "myproxy:80".
6562 ProxyConfig proxy_config;
6563 proxy_config.set_auto_detect(true);
6564 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6565
6566 CapturingProxyResolver capturing_proxy_resolver;
6567 session_deps_.proxy_resolution_service =
6568 std::make_unique<ProxyResolutionService>(
6569 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6570 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6571 std::make_unique<CapturingProxyResolverFactory>(
6572 &capturing_proxy_resolver),
6573 nullptr);
6574
6575 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6576 // Fetch https://proxy:70/ via HTTP/2.
6577 SpdyTestUtil spdy_util1;
6578 spdy::SpdySerializedFrame req(
6579 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6580 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6581
6582 spdy::SpdySerializedFrame resp(
6583 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6584 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6585 MockRead spdy_reads1[] = {
6586 CreateMockRead(resp, 1),
6587 CreateMockRead(data, 2),
6588 MockRead(ASYNC, 0, 3),
6589 };
6590 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6591 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6592
6593 SpdyTestUtil spdy_util2;
6594 // CONNECT to www.example.org:443 via HTTP/2.
6595 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046596 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6597 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116598 // fetch https://www.example.org/ via HTTP/2.
6599 const char kMyUrl[] = "https://www.example.org/";
6600 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6601 spdy::SpdySerializedFrame wrapped_get(
6602 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6603 spdy::SpdySerializedFrame conn_resp(
6604 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6605 spdy::SpdySerializedFrame get_resp(
6606 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6607 spdy::SpdySerializedFrame wrapped_get_resp(
6608 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6609 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6610 spdy::SpdySerializedFrame wrapped_body(
6611 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6612 spdy::SpdySerializedFrame window_update_get_resp(
6613 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6614 spdy::SpdySerializedFrame window_update_body(
6615 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6616
6617 MockWrite spdy_writes2[] = {
6618 CreateMockWrite(connect, 0),
6619 CreateMockWrite(wrapped_get, 2),
6620 CreateMockWrite(window_update_get_resp, 6),
6621 CreateMockWrite(window_update_body, 7),
6622 };
6623
6624 MockRead spdy_reads2[] = {
6625 CreateMockRead(conn_resp, 1, ASYNC),
6626 MockRead(ASYNC, ERR_IO_PENDING, 3),
6627 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6628 CreateMockRead(wrapped_body, 5, ASYNC),
6629 MockRead(ASYNC, 0, 8),
6630 };
6631
6632 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6633 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6634
6635 SSLSocketDataProvider ssl(ASYNC, OK);
6636 ssl.next_proto = kProtoHTTP2;
6637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6638 SSLSocketDataProvider ssl2(ASYNC, OK);
6639 ssl2.next_proto = kProtoHTTP2;
6640 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6641 SSLSocketDataProvider ssl3(ASYNC, OK);
6642 ssl3.next_proto = kProtoHTTP2;
6643 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6644
6645 TestCompletionCallback callback;
6646 std::string response_data;
6647
6648 // Make a direct HTTP/2 request to proxy:70.
6649 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6650 HttpRequestInfo request1;
6651 request1.method = "GET";
6652 request1.url = GURL("https://proxy:70/");
6653 request1.traffic_annotation =
6654 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6655 HttpNetworkTransaction trans1(LOWEST, session.get());
6656 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6657 NetLogWithSource())),
6658 IsOk());
6659 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6660 RunUntilIdle();
6661
6662 // Make a request using proxy:70 as a HTTP/2 proxy.
6663 capturing_proxy_resolver.set_proxy_server(
6664 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6665 HttpRequestInfo request2;
6666 request2.method = "GET";
6667 request2.url = GURL("https://www.example.org/");
6668 request2.traffic_annotation =
6669 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6670
6671 HttpNetworkTransaction trans2(LOWEST, session.get());
6672 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6673 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6674
6675 // Allow the SpdyProxyClientSocket's write callback to complete.
6676 base::RunLoop().RunUntilIdle();
6677 // Now allow the read of the response to complete.
6678 spdy_data2.Resume();
6679 rv = callback.WaitForResult();
6680 EXPECT_THAT(rv, IsOk());
6681
6682 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6683 ASSERT_TRUE(response2);
6684 ASSERT_TRUE(response2->headers);
6685 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6686
6687 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6688 EXPECT_EQ(kUploadData, response_data);
6689}
6690
[email protected]2df19bb2010-08-25 20:13:466691// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016692TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466693 HttpRequestInfo request;
6694 request.method = "GET";
bncce36dca22015-04-21 22:11:236695 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466696 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296697 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:106698 request.traffic_annotation =
6699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466700
[email protected]79cb5c12011-09-12 13:12:046701 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496702 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6703 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516704 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076705 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096706 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276707
[email protected]2df19bb2010-08-25 20:13:466708 // Since we have proxy, should use full url
6709 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166710 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6711 "Host: www.example.org\r\n"
6712 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466713
bnc691fda62016-08-12 00:43:166714 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236715 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166716 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6717 "Host: www.example.org\r\n"
6718 "Proxy-Connection: keep-alive\r\n"
6719 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466720 };
6721
6722 // The proxy responds to the GET with a 407, using a persistent
6723 // connection.
6724 MockRead data_reads1[] = {
6725 // No credentials.
6726 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6727 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6728 MockRead("Proxy-Connection: keep-alive\r\n"),
6729 MockRead("Content-Length: 0\r\n\r\n"),
6730
6731 MockRead("HTTP/1.1 200 OK\r\n"),
6732 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6733 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066734 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466735 };
6736
Ryan Sleevib8d7ea02018-05-07 20:01:016737 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076738 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066739 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466741
[email protected]49639fa2011-12-20 23:22:416742 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466743
bnc691fda62016-08-12 00:43:166744 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506745
bnc691fda62016-08-12 00:43:166746 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016747 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466748
6749 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016750 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466751
[email protected]58e32bb2013-01-21 18:23:256752 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166753 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256754 TestLoadTimingNotReused(load_timing_info,
6755 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6756
bnc691fda62016-08-12 00:43:166757 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526758 ASSERT_TRUE(response);
6759 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466760 EXPECT_EQ(407, response->headers->response_code());
6761 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586762 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506763 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466764
[email protected]49639fa2011-12-20 23:22:416765 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466766
bnc691fda62016-08-12 00:43:166767 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016768 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466769
6770 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016771 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466772
[email protected]58e32bb2013-01-21 18:23:256773 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166774 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256775 // Retrying with HTTP AUTH is considered to be reusing a socket.
6776 TestLoadTimingReused(load_timing_info);
6777
bnc691fda62016-08-12 00:43:166778 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526779 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466780
6781 EXPECT_TRUE(response->headers->IsKeepAlive());
6782 EXPECT_EQ(200, response->headers->response_code());
6783 EXPECT_EQ(100, response->headers->GetContentLength());
6784 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506785 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466786
6787 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586788 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466789}
6790
[email protected]23e482282013-06-14 16:08:026791void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086792 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426793 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086794 request.method = "GET";
bncce36dca22015-04-21 22:11:236795 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106796 request.traffic_annotation =
6797 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086798
[email protected]cb9bf6ca2011-01-28 13:15:276799 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496800 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6801 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276803
[email protected]c744cf22009-02-27 07:28:086804 // Since we have proxy, should try to establish tunnel.
6805 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176806 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6807 "Host: www.example.org:443\r\n"
6808 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086809 };
6810
6811 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236812 status, MockRead("Content-Length: 10\r\n\r\n"),
6813 // No response body because the test stops reading here.
6814 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086815 };
6816
Ryan Sleevib8d7ea02018-05-07 20:01:016817 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076818 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086819
[email protected]49639fa2011-12-20 23:22:416820 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086821
bnc691fda62016-08-12 00:43:166822 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506823
tfarina42834112016-09-22 13:38:206824 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086826
6827 rv = callback.WaitForResult();
6828 EXPECT_EQ(expected_status, rv);
6829}
6830
[email protected]23e482282013-06-14 16:08:026831void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236832 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086833 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426834 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086835}
6836
bncd16676a2016-07-20 16:23:016837TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086838 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6839}
6840
bncd16676a2016-07-20 16:23:016841TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086842 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6843}
6844
bncd16676a2016-07-20 16:23:016845TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086846 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6847}
6848
bncd16676a2016-07-20 16:23:016849TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086850 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6851}
6852
bncd16676a2016-07-20 16:23:016853TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086854 ConnectStatusHelper(
6855 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6856}
6857
bncd16676a2016-07-20 16:23:016858TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086859 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6860}
6861
bncd16676a2016-07-20 16:23:016862TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086863 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6864}
6865
bncd16676a2016-07-20 16:23:016866TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086867 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6868}
6869
bncd16676a2016-07-20 16:23:016870TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086871 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6872}
6873
bncd16676a2016-07-20 16:23:016874TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086875 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6876}
6877
bncd16676a2016-07-20 16:23:016878TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086879 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6880}
6881
bncd16676a2016-07-20 16:23:016882TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086883 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6884}
6885
bncd16676a2016-07-20 16:23:016886TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086887 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6888}
6889
bncd16676a2016-07-20 16:23:016890TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086891 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6892}
6893
bncd16676a2016-07-20 16:23:016894TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086895 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6896}
6897
bncd16676a2016-07-20 16:23:016898TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086899 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6900}
6901
bncd16676a2016-07-20 16:23:016902TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376903 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6904}
6905
bncd16676a2016-07-20 16:23:016906TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086907 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6908}
6909
bncd16676a2016-07-20 16:23:016910TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086911 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6912}
6913
bncd16676a2016-07-20 16:23:016914TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086915 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6916}
6917
bncd16676a2016-07-20 16:23:016918TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086919 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6920}
6921
bncd16676a2016-07-20 16:23:016922TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086923 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6924}
6925
bncd16676a2016-07-20 16:23:016926TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086927 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6928}
6929
bncd16676a2016-07-20 16:23:016930TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086931 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6932}
6933
bncd16676a2016-07-20 16:23:016934TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086935 ConnectStatusHelperWithExpectedStatus(
6936 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546937 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086938}
6939
bncd16676a2016-07-20 16:23:016940TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086941 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6942}
6943
bncd16676a2016-07-20 16:23:016944TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086945 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6946}
6947
bncd16676a2016-07-20 16:23:016948TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086949 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6950}
6951
bncd16676a2016-07-20 16:23:016952TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086953 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6954}
6955
bncd16676a2016-07-20 16:23:016956TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086957 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6958}
6959
bncd16676a2016-07-20 16:23:016960TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086961 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6962}
6963
bncd16676a2016-07-20 16:23:016964TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086965 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6966}
6967
bncd16676a2016-07-20 16:23:016968TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086969 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6970}
6971
bncd16676a2016-07-20 16:23:016972TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086973 ConnectStatusHelper(
6974 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
6975}
6976
bncd16676a2016-07-20 16:23:016977TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:086978 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
6979}
6980
bncd16676a2016-07-20 16:23:016981TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:086982 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
6983}
6984
bncd16676a2016-07-20 16:23:016985TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:086986 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
6987}
6988
bncd16676a2016-07-20 16:23:016989TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:086990 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
6991}
6992
bncd16676a2016-07-20 16:23:016993TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:086994 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
6995}
6996
bncd16676a2016-07-20 16:23:016997TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:086998 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
6999}
7000
bncd16676a2016-07-20 16:23:017001TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087002 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7003}
7004
[email protected]038e9a32008-10-08 22:40:167005// Test the flow when both the proxy server AND origin server require
7006// authentication. Again, this uses basic auth for both since that is
7007// the simplest to mock.
bncd16676a2016-07-20 16:23:017008TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277009 HttpRequestInfo request;
7010 request.method = "GET";
bncce36dca22015-04-21 22:11:237011 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107012 request.traffic_annotation =
7013 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277014
[email protected]038e9a32008-10-08 22:40:167015 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497016 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7017 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097018 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077019
bnc691fda62016-08-12 00:43:167020 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167021
[email protected]f9ee6b52008-11-08 06:46:237022 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237023 MockWrite(
7024 "GET http://www.example.org/ HTTP/1.1\r\n"
7025 "Host: www.example.org\r\n"
7026 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237027 };
7028
[email protected]038e9a32008-10-08 22:40:167029 MockRead data_reads1[] = {
7030 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7031 // Give a couple authenticate options (only the middle one is actually
7032 // supported).
[email protected]22927ad2009-09-21 19:56:197033 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167034 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7035 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7036 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7037 // Large content-length -- won't matter, as connection will be reset.
7038 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067039 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167040 };
7041
bnc691fda62016-08-12 00:43:167042 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167043 // request we should be issuing -- the final header line contains the
7044 // proxy's credentials.
7045 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237046 MockWrite(
7047 "GET http://www.example.org/ HTTP/1.1\r\n"
7048 "Host: www.example.org\r\n"
7049 "Proxy-Connection: keep-alive\r\n"
7050 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167051 };
7052
7053 // Now the proxy server lets the request pass through to origin server.
7054 // The origin server responds with a 401.
7055 MockRead data_reads2[] = {
7056 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7057 // Note: We are using the same realm-name as the proxy server. This is
7058 // completely valid, as realms are unique across hosts.
7059 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7060 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7061 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067062 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167063 };
7064
bnc691fda62016-08-12 00:43:167065 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167066 // the credentials for both the proxy and origin server.
7067 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237068 MockWrite(
7069 "GET http://www.example.org/ HTTP/1.1\r\n"
7070 "Host: www.example.org\r\n"
7071 "Proxy-Connection: keep-alive\r\n"
7072 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7073 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167074 };
7075
7076 // Lastly we get the desired content.
7077 MockRead data_reads3[] = {
7078 MockRead("HTTP/1.0 200 OK\r\n"),
7079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7080 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067081 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167082 };
7083
Ryan Sleevib8d7ea02018-05-07 20:01:017084 StaticSocketDataProvider data1(data_reads1, data_writes1);
7085 StaticSocketDataProvider data2(data_reads2, data_writes2);
7086 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077087 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7088 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7089 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167090
[email protected]49639fa2011-12-20 23:22:417091 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167092
tfarina42834112016-09-22 13:38:207093 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017094 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167095
7096 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017097 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167098
bnc691fda62016-08-12 00:43:167099 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527100 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587101 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167102
[email protected]49639fa2011-12-20 23:22:417103 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167104
bnc691fda62016-08-12 00:43:167105 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017106 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167107
7108 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017109 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167110
bnc691fda62016-08-12 00:43:167111 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527112 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587113 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167114
[email protected]49639fa2011-12-20 23:22:417115 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167116
bnc691fda62016-08-12 00:43:167117 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7118 callback3.callback());
robpercival214763f2016-07-01 23:27:017119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167120
7121 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017122 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167123
bnc691fda62016-08-12 00:43:167124 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587125 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167126 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167127}
[email protected]4ddaf2502008-10-23 18:26:197128
[email protected]ea9dc9a2009-09-05 00:43:327129// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7130// can't hook into its internals to cause it to generate predictable NTLM
7131// authorization headers.
7132#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377133// The NTLM authentication unit tests are based on known test data from the
7134// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7135// flow rather than the implementation of the NTLM protocol. See net/ntlm
7136// for the implementation and testing of the protocol.
7137//
7138// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297139
7140// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557141TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427142 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247143 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557144 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107145 request.traffic_annotation =
7146 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547147
7148 // Ensure load is not disrupted by flags which suppress behaviour specific
7149 // to other auth schemes.
7150 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247151
Zentaro Kavanagh6ccee512017-09-28 18:34:097152 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7153 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277155
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377156 // Generate the NTLM messages based on known test data.
7157 std::string negotiate_msg;
7158 std::string challenge_msg;
7159 std::string authenticate_msg;
7160 base::Base64Encode(
7161 base::StringPiece(
7162 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247163 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377164 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557165 base::Base64Encode(
7166 base::StringPiece(
7167 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247168 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557169 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377170 base::Base64Encode(
7171 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097172 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557173 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247174 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557175 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377176 &authenticate_msg);
7177
[email protected]3f918782009-02-28 01:29:247178 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557179 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7180 "Host: server\r\n"
7181 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247182 };
7183
7184 MockRead data_reads1[] = {
7185 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047186 // Negotiate and NTLM are often requested together. However, we only want
7187 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7188 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247189 MockRead("WWW-Authenticate: NTLM\r\n"),
7190 MockRead("Connection: close\r\n"),
7191 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367192 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247193 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247194 };
7195
7196 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167197 // After restarting with a null identity, this is the
7198 // request we should be issuing -- the final header line contains a Type
7199 // 1 message.
7200 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557201 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167202 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377203 "Authorization: NTLM "),
7204 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247205
bnc691fda62016-08-12 00:43:167206 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377207 // (using correct credentials). The second request continues on the
7208 // same connection.
bnc691fda62016-08-12 00:43:167209 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557210 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167211 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377212 "Authorization: NTLM "),
7213 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247214 };
7215
7216 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027217 // The origin server responds with a Type 2 message.
7218 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377219 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7220 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027221 MockRead("Content-Type: text/html\r\n\r\n"),
7222 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247223
Bence Béky1e4ef192017-09-18 19:58:027224 // Lastly we get the desired content.
7225 MockRead("HTTP/1.1 200 OK\r\n"),
7226 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7227 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247228 };
7229
Ryan Sleevib8d7ea02018-05-07 20:01:017230 StaticSocketDataProvider data1(data_reads1, data_writes1);
7231 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077232 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7233 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247234
Bence Béky83eb3512017-09-05 12:56:097235 SSLSocketDataProvider ssl1(ASYNC, OK);
7236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7237 SSLSocketDataProvider ssl2(ASYNC, OK);
7238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7239
[email protected]49639fa2011-12-20 23:22:417240 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247241
bnc691fda62016-08-12 00:43:167242 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507243
tfarina42834112016-09-22 13:38:207244 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247246
7247 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017248 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247249
bnc691fda62016-08-12 00:43:167250 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227251
bnc691fda62016-08-12 00:43:167252 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527253 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587254 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247255
[email protected]49639fa2011-12-20 23:22:417256 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257257
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377258 rv = trans.RestartWithAuth(
7259 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7260 callback2.callback());
robpercival214763f2016-07-01 23:27:017261 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257262
7263 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017264 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257265
bnc691fda62016-08-12 00:43:167266 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257267
bnc691fda62016-08-12 00:43:167268 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527269 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587270 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257271
[email protected]49639fa2011-12-20 23:22:417272 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247273
bnc691fda62016-08-12 00:43:167274 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017275 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247276
[email protected]0757e7702009-03-27 04:00:227277 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017278 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247279
bnc691fda62016-08-12 00:43:167280 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527281 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587282 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027283 EXPECT_EQ(14, response->headers->GetContentLength());
7284
7285 std::string response_data;
7286 rv = ReadTransaction(&trans, &response_data);
7287 EXPECT_THAT(rv, IsOk());
7288 EXPECT_EQ("Please Login\r\n", response_data);
7289
7290 EXPECT_TRUE(data1.AllReadDataConsumed());
7291 EXPECT_TRUE(data1.AllWriteDataConsumed());
7292 EXPECT_TRUE(data2.AllReadDataConsumed());
7293 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247294}
7295
[email protected]385a4672009-03-11 22:21:297296// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557297TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427298 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297299 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557300 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107301 request.traffic_annotation =
7302 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297303
Zentaro Kavanagh6ccee512017-09-28 18:34:097304 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7305 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097306 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277307
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377308 // Generate the NTLM messages based on known test data.
7309 std::string negotiate_msg;
7310 std::string challenge_msg;
7311 std::string authenticate_msg;
7312 base::Base64Encode(
7313 base::StringPiece(
7314 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247315 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377316 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557317 base::Base64Encode(
7318 base::StringPiece(
7319 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247320 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557321 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377322 base::Base64Encode(
7323 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097324 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557325 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247326 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557327 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377328 &authenticate_msg);
7329
7330 // The authenticate message when |kWrongPassword| is sent.
7331 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557332 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7333 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7334 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7335 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7336 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7337 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377338
Zentaro Kavanagh1890a3d2018-01-29 19:52:557339 // Sanity check that it's the same length as the correct authenticate message
7340 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377341 ASSERT_EQ(authenticate_msg.length(),
7342 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557343 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377344
[email protected]385a4672009-03-11 22:21:297345 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557346 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7347 "Host: server\r\n"
7348 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297349 };
7350
7351 MockRead data_reads1[] = {
7352 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047353 // Negotiate and NTLM are often requested together. However, we only want
7354 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7355 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297356 MockRead("WWW-Authenticate: NTLM\r\n"),
7357 MockRead("Connection: close\r\n"),
7358 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367359 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297360 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297361 };
7362
7363 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167364 // After restarting with a null identity, this is the
7365 // request we should be issuing -- the final header line contains a Type
7366 // 1 message.
7367 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557368 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167369 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377370 "Authorization: NTLM "),
7371 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297372
bnc691fda62016-08-12 00:43:167373 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377374 // (using incorrect credentials). The second request continues on the
7375 // same connection.
bnc691fda62016-08-12 00:43:167376 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557377 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167378 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377379 "Authorization: NTLM "),
7380 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297381 };
7382
7383 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377384 // The origin server responds with a Type 2 message.
7385 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7386 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7387 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7388 MockRead("Content-Type: text/html\r\n\r\n"),
7389 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297390
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377391 // Wrong password.
7392 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7393 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7394 MockRead("Content-Length: 42\r\n"),
7395 MockRead("Content-Type: text/html\r\n\r\n"),
7396 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297397 };
7398
7399 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167400 // After restarting with a null identity, this is the
7401 // request we should be issuing -- the final header line contains a Type
7402 // 1 message.
7403 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557404 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167405 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377406 "Authorization: NTLM "),
7407 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297408
bnc691fda62016-08-12 00:43:167409 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7410 // (the credentials for the origin server). The second request continues
7411 // on the same connection.
7412 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557413 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167414 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377415 "Authorization: NTLM "),
7416 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297417 };
7418
7419 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027420 // The origin server responds with a Type 2 message.
7421 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377422 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7423 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027424 MockRead("Content-Type: text/html\r\n\r\n"),
7425 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297426
Bence Béky1e4ef192017-09-18 19:58:027427 // Lastly we get the desired content.
7428 MockRead("HTTP/1.1 200 OK\r\n"),
7429 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7430 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297431 };
7432
Ryan Sleevib8d7ea02018-05-07 20:01:017433 StaticSocketDataProvider data1(data_reads1, data_writes1);
7434 StaticSocketDataProvider data2(data_reads2, data_writes2);
7435 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077436 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7437 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7438 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297439
Bence Béky83eb3512017-09-05 12:56:097440 SSLSocketDataProvider ssl1(ASYNC, OK);
7441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7442 SSLSocketDataProvider ssl2(ASYNC, OK);
7443 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7444 SSLSocketDataProvider ssl3(ASYNC, OK);
7445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7446
[email protected]49639fa2011-12-20 23:22:417447 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297448
bnc691fda62016-08-12 00:43:167449 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507450
tfarina42834112016-09-22 13:38:207451 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297453
7454 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017455 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297456
bnc691fda62016-08-12 00:43:167457 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297458
bnc691fda62016-08-12 00:43:167459 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527460 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587461 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297462
[email protected]49639fa2011-12-20 23:22:417463 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297464
[email protected]0757e7702009-03-27 04:00:227465 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377466 rv = trans.RestartWithAuth(
7467 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7468 callback2.callback());
robpercival214763f2016-07-01 23:27:017469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297470
[email protected]10af5fe72011-01-31 16:17:257471 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017472 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297473
bnc691fda62016-08-12 00:43:167474 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417475 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167476 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257478 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017479 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167480 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227481
bnc691fda62016-08-12 00:43:167482 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527483 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587484 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227485
[email protected]49639fa2011-12-20 23:22:417486 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227487
7488 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377489 rv = trans.RestartWithAuth(
7490 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7491 callback4.callback());
robpercival214763f2016-07-01 23:27:017492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257493
7494 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017495 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257496
bnc691fda62016-08-12 00:43:167497 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257498
[email protected]49639fa2011-12-20 23:22:417499 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257500
7501 // One more roundtrip
bnc691fda62016-08-12 00:43:167502 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017503 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227504
7505 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017506 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227507
bnc691fda62016-08-12 00:43:167508 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587509 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027510 EXPECT_EQ(14, response->headers->GetContentLength());
7511
7512 std::string response_data;
7513 rv = ReadTransaction(&trans, &response_data);
7514 EXPECT_THAT(rv, IsOk());
7515 EXPECT_EQ("Please Login\r\n", response_data);
7516
7517 EXPECT_TRUE(data1.AllReadDataConsumed());
7518 EXPECT_TRUE(data1.AllWriteDataConsumed());
7519 EXPECT_TRUE(data2.AllReadDataConsumed());
7520 EXPECT_TRUE(data2.AllWriteDataConsumed());
7521 EXPECT_TRUE(data3.AllReadDataConsumed());
7522 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297523}
Bence Béky83eb3512017-09-05 12:56:097524
Bence Béky3238f2e12017-09-22 22:44:497525// Server requests NTLM authentication, which is not supported over HTTP/2.
7526// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097527TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097528 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7529 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097530
Zentaro Kavanagh1890a3d2018-01-29 19:52:557531 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097532
7533 HttpRequestInfo request;
7534 request.method = "GET";
7535 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:107536 request.traffic_annotation =
7537 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097538
7539 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137540 spdy::SpdyHeaderBlock request_headers0(
7541 spdy_util_.ConstructGetHeaderBlock(kUrl));
7542 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097543 1, std::move(request_headers0), LOWEST, true));
7544
Ryan Hamilton0239aac2018-05-19 00:03:137545 spdy::SpdyHeaderBlock response_headers0;
7546 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097547 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137548 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097549 1, std::move(response_headers0), true));
7550
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377551 // Stream 1 is closed.
7552 spdy_util_.UpdateWithStreamDestruction(1);
7553
7554 // Generate the NTLM messages based on known test data.
7555 std::string negotiate_msg;
7556 std::string challenge_msg;
7557 std::string authenticate_msg;
7558 base::Base64Encode(
7559 base::StringPiece(
7560 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247561 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377562 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557563 base::Base64Encode(
7564 base::StringPiece(
7565 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247566 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557567 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377568 base::Base64Encode(
7569 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097570 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557571 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247572 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557573 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377574 &authenticate_msg);
7575
7576 // Retry with authorization header.
Ryan Hamilton0239aac2018-05-19 00:03:137577 spdy::SpdyHeaderBlock request_headers1(
7578 spdy_util_.ConstructGetHeaderBlock(kUrl));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377579 request_headers1["authorization"] = std::string("NTLM ") + negotiate_msg;
Ryan Hamilton0239aac2018-05-19 00:03:137580 spdy::SpdySerializedFrame request1(spdy_util_.ConstructSpdyHeaders(
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377581 3, std::move(request_headers1), LOWEST, true));
7582
Ryan Hamilton0239aac2018-05-19 00:03:137583 spdy::SpdySerializedFrame rst(
7584 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377585
Bence Béky3238f2e12017-09-22 22:44:497586 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
7587 MockRead reads0[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
Bence Béky83eb3512017-09-05 12:56:097588
7589 // Retry yet again using HTTP/1.1.
7590 MockWrite writes1[] = {
7591 // After restarting with a null identity, this is the
7592 // request we should be issuing -- the final header line contains a Type
7593 // 1 message.
7594 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557595 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097596 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377597 "Authorization: NTLM "),
7598 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097599
7600 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7601 // (the credentials for the origin server). The second request continues
7602 // on the same connection.
7603 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557604 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097605 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377606 "Authorization: NTLM "),
7607 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097608 };
7609
7610 MockRead reads1[] = {
7611 // The origin server responds with a Type 2 message.
7612 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377613 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7614 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097615 MockRead("Content-Type: text/html\r\n\r\n"),
7616 MockRead("You are not authorized to view this page\r\n"),
7617
7618 // Lastly we get the desired content.
7619 MockRead("HTTP/1.1 200 OK\r\n"),
7620 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027621 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097622 };
Ryan Sleevib8d7ea02018-05-07 20:01:017623 SequencedSocketData data0(reads0, writes0);
7624 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097625 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7626 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7627
7628 SSLSocketDataProvider ssl0(ASYNC, OK);
7629 ssl0.next_proto = kProtoHTTP2;
7630 SSLSocketDataProvider ssl1(ASYNC, OK);
7631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7632 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7633
7634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7636
7637 TestCompletionCallback callback1;
7638 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7640
7641 rv = callback1.WaitForResult();
7642 EXPECT_THAT(rv, IsOk());
7643
7644 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7645
7646 const HttpResponseInfo* response = trans.GetResponseInfo();
7647 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587648 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097649
7650 TestCompletionCallback callback2;
7651
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377652 rv = trans.RestartWithAuth(
7653 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7654 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097655 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7656
7657 rv = callback2.WaitForResult();
7658 EXPECT_THAT(rv, IsOk());
7659
7660 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7661
7662 response = trans.GetResponseInfo();
7663 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587664 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097665
7666 TestCompletionCallback callback3;
7667
7668 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7669 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7670
7671 rv = callback3.WaitForResult();
7672 EXPECT_THAT(rv, IsOk());
7673
7674 response = trans.GetResponseInfo();
7675 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587676 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027677 EXPECT_EQ(14, response->headers->GetContentLength());
7678
7679 std::string response_data;
7680 rv = ReadTransaction(&trans, &response_data);
7681 EXPECT_THAT(rv, IsOk());
7682 EXPECT_EQ("Please Login\r\n", response_data);
7683
7684 EXPECT_TRUE(data0.AllReadDataConsumed());
7685 EXPECT_TRUE(data0.AllWriteDataConsumed());
7686 EXPECT_TRUE(data1.AllReadDataConsumed());
7687 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097688}
David Benjamin5cb91132018-04-06 05:54:497689
7690// Test that, if we have an NTLM proxy and the origin resets the connection, we
7691// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377692// regression test for https://crbug.com/823387. The version interference probe
7693// has since been removed, but retain the regression test so we can update it if
7694// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497695TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7696 // The NTLM test data expects the proxy to be named 'server'. The origin is
7697 // https://origin/.
7698 session_deps_.proxy_resolution_service =
7699 ProxyResolutionService::CreateFixedFromPacResult(
7700 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7701
David Benjamin151ec6b2019-08-02 19:38:527702 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:497703 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077704 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497705
7706 HttpRequestInfo request;
7707 request.method = "GET";
7708 request.url = GURL("https://origin/");
7709 request.traffic_annotation =
7710 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7711
7712 // Ensure load is not disrupted by flags which suppress behaviour specific
7713 // to other auth schemes.
7714 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7715
7716 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7717 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7719
7720 // Generate the NTLM messages based on known test data.
7721 std::string negotiate_msg;
7722 std::string challenge_msg;
7723 std::string authenticate_msg;
7724 base::Base64Encode(
7725 base::StringPiece(
7726 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247727 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497728 &negotiate_msg);
7729 base::Base64Encode(
7730 base::StringPiece(
7731 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247732 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497733 &challenge_msg);
7734 base::Base64Encode(
7735 base::StringPiece(
7736 reinterpret_cast<const char*>(
7737 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247738 base::size(
David Benjamin5cb91132018-04-06 05:54:497739 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7740 &authenticate_msg);
7741
7742 MockWrite data_writes[] = {
7743 // The initial CONNECT request.
7744 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7745 "Host: origin:443\r\n"
7746 "Proxy-Connection: keep-alive\r\n\r\n"),
7747
7748 // After restarting with an identity.
7749 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7750 "Host: origin:443\r\n"
7751 "Proxy-Connection: keep-alive\r\n"
7752 "Proxy-Authorization: NTLM "),
7753 MockWrite(negotiate_msg.c_str()),
7754 // End headers.
7755 MockWrite("\r\n\r\n"),
7756
7757 // The second restart.
7758 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7759 "Host: origin:443\r\n"
7760 "Proxy-Connection: keep-alive\r\n"
7761 "Proxy-Authorization: NTLM "),
7762 MockWrite(authenticate_msg.c_str()),
7763 // End headers.
7764 MockWrite("\r\n\r\n"),
7765 };
7766
7767 MockRead data_reads[] = {
7768 // The initial NTLM response.
7769 MockRead("HTTP/1.1 407 Access Denied\r\n"
7770 "Content-Length: 0\r\n"
7771 "Proxy-Authenticate: NTLM\r\n\r\n"),
7772
7773 // The NTLM challenge message.
7774 MockRead("HTTP/1.1 407 Access Denied\r\n"
7775 "Content-Length: 0\r\n"
7776 "Proxy-Authenticate: NTLM "),
7777 MockRead(challenge_msg.c_str()),
7778 // End headers.
7779 MockRead("\r\n\r\n"),
7780
7781 // Finally the tunnel is established.
7782 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7783 };
7784
Ryan Sleevib8d7ea02018-05-07 20:01:017785 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497786 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497787 session_deps_.socket_factory->AddSocketDataProvider(&data);
7788 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497789
7790 // Start the transaction. The proxy responds with an NTLM authentication
7791 // request.
7792 TestCompletionCallback callback;
7793 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7794 int rv = callback.GetResult(
7795 trans.Start(&request, callback.callback(), NetLogWithSource()));
7796
7797 EXPECT_THAT(rv, IsOk());
7798 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7799 const HttpResponseInfo* response = trans.GetResponseInfo();
7800 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587801 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497802
David Benjamind61bd532019-04-23 21:11:377803 // Configure credentials and restart. The proxy responds with the challenge
7804 // message.
David Benjamin5cb91132018-04-06 05:54:497805 rv = callback.GetResult(trans.RestartWithAuth(
7806 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7807 callback.callback()));
7808 EXPECT_THAT(rv, IsOk());
7809 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7810 response = trans.GetResponseInfo();
7811 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587812 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497813
David Benjamind61bd532019-04-23 21:11:377814 // Restart once more. The tunnel will be established and then the SSL
7815 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497816 rv = callback.GetResult(
7817 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7818 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7819}
7820
[email protected]ea9dc9a2009-09-05 00:43:327821#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297822
[email protected]4ddaf2502008-10-23 18:26:197823// Test reading a server response which has only headers, and no body.
7824// After some maximum number of bytes is consumed, the transaction should
7825// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:017826TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:427827 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:197828 request.method = "GET";
bncce36dca22015-04-21 22:11:237829 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107830 request.traffic_annotation =
7831 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:197832
danakj1fd259a02016-04-16 03:17:097833 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:167834 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277835
[email protected]b75b7b2f2009-10-06 00:54:537836 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:437837 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:537838 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:197839
7840 MockRead data_reads[] = {
7841 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:067842 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:197843 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:067844 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:197845 };
Ryan Sleevib8d7ea02018-05-07 20:01:017846 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077847 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:197848
[email protected]49639fa2011-12-20 23:22:417849 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:197850
tfarina42834112016-09-22 13:38:207851 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017852 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:197853
7854 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017855 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:197856}
[email protected]f4e426b2008-11-05 00:24:497857
7858// Make sure that we don't try to reuse a TCPClientSocket when failing to
7859// establish tunnel.
7860// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:017861TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:277862 HttpRequestInfo request;
7863 request.method = "GET";
bncce36dca22015-04-21 22:11:237864 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107865 request.traffic_annotation =
7866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277867
[email protected]f4e426b2008-11-05 00:24:497868 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497869 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7870 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:017871
danakj1fd259a02016-04-16 03:17:097872 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:497873
bnc87dcefc2017-05-25 12:47:587874 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197875 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:497876
[email protected]f4e426b2008-11-05 00:24:497877 // Since we have proxy, should try to establish tunnel.
7878 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:177879 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7880 "Host: www.example.org:443\r\n"
7881 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:497882 };
7883
[email protected]77848d12008-11-14 00:00:227884 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:497885 // connection. Usually a proxy would return 501 (not implemented),
7886 // or 200 (tunnel established).
7887 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:237888 MockRead("HTTP/1.1 404 Not Found\r\n"),
7889 MockRead("Content-Length: 10\r\n\r\n"),
7890 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:497891 };
7892
Ryan Sleevib8d7ea02018-05-07 20:01:017893 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077894 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:497895
[email protected]49639fa2011-12-20 23:22:417896 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:497897
tfarina42834112016-09-22 13:38:207898 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017899 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:497900
7901 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017902 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:497903
[email protected]b4404c02009-04-10 16:38:527904 // Empty the current queue. This is necessary because idle sockets are
7905 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557906 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:527907
[email protected]f4e426b2008-11-05 00:24:497908 // We now check to make sure the TCPClientSocket was not added back to
7909 // the pool.
[email protected]90499482013-06-01 00:39:507910 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497911 trans.reset();
fdoray92e35a72016-06-10 15:54:557912 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:497913 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:507914 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497915}
[email protected]372d34a2008-11-05 21:30:517916
[email protected]1b157c02009-04-21 01:55:407917// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:017918TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:427919 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:407920 request.method = "GET";
bncce36dca22015-04-21 22:11:237921 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107922 request.traffic_annotation =
7923 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:407924
danakj1fd259a02016-04-16 03:17:097925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277926
bnc691fda62016-08-12 00:43:167927 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277928
[email protected]1b157c02009-04-21 01:55:407929 MockRead data_reads[] = {
7930 // A part of the response body is received with the response headers.
7931 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
7932 // The rest of the response body is received in two parts.
7933 MockRead("lo"),
7934 MockRead(" world"),
7935 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:067936 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:407937 };
7938
Ryan Sleevib8d7ea02018-05-07 20:01:017939 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077940 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:407941
[email protected]49639fa2011-12-20 23:22:417942 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:407943
tfarina42834112016-09-22 13:38:207944 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017945 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:407946
7947 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017948 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407949
bnc691fda62016-08-12 00:43:167950 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527951 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:407952
wezca1070932016-05-26 20:30:527953 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:407954 std::string status_line = response->headers->GetStatusLine();
7955 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
7956
[email protected]90499482013-06-01 00:39:507957 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407958
7959 std::string response_data;
bnc691fda62016-08-12 00:43:167960 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:017961 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407962 EXPECT_EQ("hello world", response_data);
7963
7964 // Empty the current queue. This is necessary because idle sockets are
7965 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557966 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:407967
7968 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:507969 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407970}
7971
[email protected]76a505b2010-08-25 06:23:007972// Make sure that we recycle a SSL socket after reading all of the response
7973// body.
bncd16676a2016-07-20 16:23:017974TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:007975 HttpRequestInfo request;
7976 request.method = "GET";
bncce36dca22015-04-21 22:11:237977 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107978 request.traffic_annotation =
7979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:007980
7981 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237982 MockWrite(
7983 "GET / HTTP/1.1\r\n"
7984 "Host: www.example.org\r\n"
7985 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:007986 };
7987
7988 MockRead data_reads[] = {
7989 MockRead("HTTP/1.1 200 OK\r\n"),
7990 MockRead("Content-Length: 11\r\n\r\n"),
7991 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:067992 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:007993 };
7994
[email protected]8ddf8322012-02-23 18:08:067995 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077996 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:007997
Ryan Sleevib8d7ea02018-05-07 20:01:017998 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077999 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008000
[email protected]49639fa2011-12-20 23:22:418001 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008002
danakj1fd259a02016-04-16 03:17:098003 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168004 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008005
tfarina42834112016-09-22 13:38:208006 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008007
robpercival214763f2016-07-01 23:27:018008 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8009 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008010
bnc691fda62016-08-12 00:43:168011 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528012 ASSERT_TRUE(response);
8013 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008014 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8015
[email protected]90499482013-06-01 00:39:508016 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008017
8018 std::string response_data;
bnc691fda62016-08-12 00:43:168019 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018020 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008021 EXPECT_EQ("hello world", response_data);
8022
8023 // Empty the current queue. This is necessary because idle sockets are
8024 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558025 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008026
8027 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238028 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008029}
8030
8031// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8032// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018033TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008034 HttpRequestInfo request;
8035 request.method = "GET";
bncce36dca22015-04-21 22:11:238036 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108037 request.traffic_annotation =
8038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008039
8040 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238041 MockWrite(
8042 "GET / HTTP/1.1\r\n"
8043 "Host: www.example.org\r\n"
8044 "Connection: keep-alive\r\n\r\n"),
8045 MockWrite(
8046 "GET / HTTP/1.1\r\n"
8047 "Host: www.example.org\r\n"
8048 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008049 };
8050
8051 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428052 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8053 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008054
[email protected]8ddf8322012-02-23 18:08:068055 SSLSocketDataProvider ssl(ASYNC, OK);
8056 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078057 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8058 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008059
Ryan Sleevib8d7ea02018-05-07 20:01:018060 StaticSocketDataProvider data(data_reads, data_writes);
8061 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078062 session_deps_.socket_factory->AddSocketDataProvider(&data);
8063 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008064
[email protected]49639fa2011-12-20 23:22:418065 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008066
danakj1fd259a02016-04-16 03:17:098067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588068 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198069 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008070
tfarina42834112016-09-22 13:38:208071 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008072
robpercival214763f2016-07-01 23:27:018073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8074 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008075
8076 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528077 ASSERT_TRUE(response);
8078 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008079 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8080
[email protected]90499482013-06-01 00:39:508081 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008082
8083 std::string response_data;
8084 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018085 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008086 EXPECT_EQ("hello world", response_data);
8087
8088 // Empty the current queue. This is necessary because idle sockets are
8089 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558090 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008091
8092 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238093 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008094
8095 // Now start the second transaction, which should reuse the previous socket.
8096
bnc87dcefc2017-05-25 12:47:588097 trans =
Jeremy Roman0579ed62017-08-29 15:56:198098 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008099
tfarina42834112016-09-22 13:38:208100 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008101
robpercival214763f2016-07-01 23:27:018102 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8103 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008104
8105 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528106 ASSERT_TRUE(response);
8107 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008108 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8109
[email protected]90499482013-06-01 00:39:508110 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008111
8112 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018113 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008114 EXPECT_EQ("hello world", response_data);
8115
8116 // Empty the current queue. This is necessary because idle sockets are
8117 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558118 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008119
8120 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238121 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008122}
8123
maksim.sisov0adf8592016-07-15 06:25:568124// Grab a socket, use it, and put it back into the pool. Then, make
8125// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018126TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568127 HttpRequestInfo request;
8128 request.method = "GET";
8129 request.url = GURL("http://www.example.org/");
8130 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108131 request.traffic_annotation =
8132 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568133
8134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8135
bnc691fda62016-08-12 00:43:168136 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568137
8138 MockRead data_reads[] = {
8139 // A part of the response body is received with the response headers.
8140 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8141 // The rest of the response body is received in two parts.
8142 MockRead("lo"), MockRead(" world"),
8143 MockRead("junk"), // Should not be read!!
8144 MockRead(SYNCHRONOUS, OK),
8145 };
8146
Ryan Sleevib8d7ea02018-05-07 20:01:018147 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568148 session_deps_.socket_factory->AddSocketDataProvider(&data);
8149
8150 TestCompletionCallback callback;
8151
tfarina42834112016-09-22 13:38:208152 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568153 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8154
8155 EXPECT_THAT(callback.GetResult(rv), IsOk());
8156
bnc691fda62016-08-12 00:43:168157 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568158 ASSERT_TRUE(response);
8159 EXPECT_TRUE(response->headers);
8160 std::string status_line = response->headers->GetStatusLine();
8161 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8162
8163 // Make memory critical notification and ensure the transaction still has been
8164 // operating right.
8165 base::MemoryPressureListener::NotifyMemoryPressure(
8166 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8167 base::RunLoop().RunUntilIdle();
8168
8169 // Socket should not be flushed as long as it is not idle.
8170 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8171
8172 std::string response_data;
bnc691fda62016-08-12 00:43:168173 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568174 EXPECT_THAT(rv, IsOk());
8175 EXPECT_EQ("hello world", response_data);
8176
8177 // Empty the current queue. This is necessary because idle sockets are
8178 // added to the connection pool asynchronously with a PostTask.
8179 base::RunLoop().RunUntilIdle();
8180
8181 // We now check to make sure the socket was added back to the pool.
8182 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8183
8184 // Idle sockets should be flushed now.
8185 base::MemoryPressureListener::NotifyMemoryPressure(
8186 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8187 base::RunLoop().RunUntilIdle();
8188
8189 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8190}
8191
yucliu48f235d2018-01-11 00:59:558192// Disable idle socket closing on memory pressure.
8193// Grab a socket, use it, and put it back into the pool. Then, make
8194// low memory notification and ensure the socket pool is NOT flushed.
8195TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8196 HttpRequestInfo request;
8197 request.method = "GET";
8198 request.url = GURL("http://www.example.org/");
8199 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108200 request.traffic_annotation =
8201 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558202
8203 // Disable idle socket closing on memory pressure.
8204 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8205 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8206
8207 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8208
8209 MockRead data_reads[] = {
8210 // A part of the response body is received with the response headers.
8211 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8212 // The rest of the response body is received in two parts.
8213 MockRead("lo"), MockRead(" world"),
8214 MockRead("junk"), // Should not be read!!
8215 MockRead(SYNCHRONOUS, OK),
8216 };
8217
Ryan Sleevib8d7ea02018-05-07 20:01:018218 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558219 session_deps_.socket_factory->AddSocketDataProvider(&data);
8220
8221 TestCompletionCallback callback;
8222
8223 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8224 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8225
8226 EXPECT_THAT(callback.GetResult(rv), IsOk());
8227
8228 const HttpResponseInfo* response = trans.GetResponseInfo();
8229 ASSERT_TRUE(response);
8230 EXPECT_TRUE(response->headers);
8231 std::string status_line = response->headers->GetStatusLine();
8232 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8233
8234 // Make memory critical notification and ensure the transaction still has been
8235 // operating right.
8236 base::MemoryPressureListener::NotifyMemoryPressure(
8237 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8238 base::RunLoop().RunUntilIdle();
8239
8240 // Socket should not be flushed as long as it is not idle.
8241 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8242
8243 std::string response_data;
8244 rv = ReadTransaction(&trans, &response_data);
8245 EXPECT_THAT(rv, IsOk());
8246 EXPECT_EQ("hello world", response_data);
8247
8248 // Empty the current queue. This is necessary because idle sockets are
8249 // added to the connection pool asynchronously with a PostTask.
8250 base::RunLoop().RunUntilIdle();
8251
8252 // We now check to make sure the socket was added back to the pool.
8253 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8254
8255 // Idle sockets should NOT be flushed on moderate memory pressure.
8256 base::MemoryPressureListener::NotifyMemoryPressure(
8257 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8258 base::RunLoop().RunUntilIdle();
8259
8260 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8261
8262 // Idle sockets should NOT be flushed on critical memory pressure.
8263 base::MemoryPressureListener::NotifyMemoryPressure(
8264 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8265 base::RunLoop().RunUntilIdle();
8266
8267 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8268}
8269
maksim.sisov0adf8592016-07-15 06:25:568270// Grab an SSL socket, use it, and put it back into the pool. Then, make
8271// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018272TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568273 HttpRequestInfo request;
8274 request.method = "GET";
8275 request.url = GURL("https://www.example.org/");
8276 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108277 request.traffic_annotation =
8278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568279
8280 MockWrite data_writes[] = {
8281 MockWrite("GET / HTTP/1.1\r\n"
8282 "Host: www.example.org\r\n"
8283 "Connection: keep-alive\r\n\r\n"),
8284 };
8285
8286 MockRead data_reads[] = {
8287 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8288 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8289
8290 SSLSocketDataProvider ssl(ASYNC, OK);
8291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8292
Ryan Sleevib8d7ea02018-05-07 20:01:018293 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568294 session_deps_.socket_factory->AddSocketDataProvider(&data);
8295
8296 TestCompletionCallback callback;
8297
8298 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168299 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568300
Matt Menke9d5e2c92019-02-05 01:42:238301 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208302 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568303
8304 EXPECT_THAT(callback.GetResult(rv), IsOk());
8305
bnc691fda62016-08-12 00:43:168306 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568307 ASSERT_TRUE(response);
8308 ASSERT_TRUE(response->headers);
8309 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8310
8311 // Make memory critical notification and ensure the transaction still has been
8312 // operating right.
8313 base::MemoryPressureListener::NotifyMemoryPressure(
8314 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8315 base::RunLoop().RunUntilIdle();
8316
Matt Menke9d5e2c92019-02-05 01:42:238317 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568318
8319 std::string response_data;
bnc691fda62016-08-12 00:43:168320 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568321 EXPECT_THAT(rv, IsOk());
8322 EXPECT_EQ("hello world", response_data);
8323
8324 // Empty the current queue. This is necessary because idle sockets are
8325 // added to the connection pool asynchronously with a PostTask.
8326 base::RunLoop().RunUntilIdle();
8327
8328 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238329 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568330
8331 // Make memory notification once again and ensure idle socket is closed.
8332 base::MemoryPressureListener::NotifyMemoryPressure(
8333 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8334 base::RunLoop().RunUntilIdle();
8335
Matt Menke9d5e2c92019-02-05 01:42:238336 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568337}
8338
[email protected]b4404c02009-04-10 16:38:528339// Make sure that we recycle a socket after a zero-length response.
8340// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018341TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428342 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528343 request.method = "GET";
bncce36dca22015-04-21 22:11:238344 request.url = GURL(
8345 "http://www.example.org/csi?v=3&s=web&action=&"
8346 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8347 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8348 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:108349 request.traffic_annotation =
8350 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528351
danakj1fd259a02016-04-16 03:17:098352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278353
[email protected]b4404c02009-04-10 16:38:528354 MockRead data_reads[] = {
8355 MockRead("HTTP/1.1 204 No Content\r\n"
8356 "Content-Length: 0\r\n"
8357 "Content-Type: text/html\r\n\r\n"),
8358 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068359 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528360 };
8361
Ryan Sleevib8d7ea02018-05-07 20:01:018362 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078363 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528364
mmenkecc2298e2015-12-07 18:20:188365 // Transaction must be created after the MockReads, so it's destroyed before
8366 // them.
bnc691fda62016-08-12 00:43:168367 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188368
[email protected]49639fa2011-12-20 23:22:418369 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528370
tfarina42834112016-09-22 13:38:208371 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528373
8374 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018375 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528376
bnc691fda62016-08-12 00:43:168377 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528378 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528379
wezca1070932016-05-26 20:30:528380 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528381 std::string status_line = response->headers->GetStatusLine();
8382 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8383
[email protected]90499482013-06-01 00:39:508384 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528385
8386 std::string response_data;
bnc691fda62016-08-12 00:43:168387 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018388 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528389 EXPECT_EQ("", response_data);
8390
8391 // Empty the current queue. This is necessary because idle sockets are
8392 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558393 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528394
8395 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508396 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528397}
8398
bncd16676a2016-07-20 16:23:018399TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098400 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228401 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198402 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228403 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278404
[email protected]1c773ea12009-04-28 19:58:428405 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518406 // Transaction 1: a GET request that succeeds. The socket is recycled
8407 // after use.
8408 request[0].method = "GET";
8409 request[0].url = GURL("http://www.google.com/");
8410 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108411 request[0].traffic_annotation =
8412 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518413 // Transaction 2: a POST request. Reuses the socket kept alive from
8414 // transaction 1. The first attempts fails when writing the POST data.
8415 // This causes the transaction to retry with a new socket. The second
8416 // attempt succeeds.
8417 request[1].method = "POST";
8418 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278419 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518420 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108421 request[1].traffic_annotation =
8422 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518423
danakj1fd259a02016-04-16 03:17:098424 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518425
8426 // The first socket is used for transaction 1 and the first attempt of
8427 // transaction 2.
8428
8429 // The response of transaction 1.
8430 MockRead data_reads1[] = {
8431 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8432 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068433 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518434 };
8435 // The mock write results of transaction 1 and the first attempt of
8436 // transaction 2.
8437 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068438 MockWrite(SYNCHRONOUS, 64), // GET
8439 MockWrite(SYNCHRONOUS, 93), // POST
8440 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518441 };
Ryan Sleevib8d7ea02018-05-07 20:01:018442 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518443
8444 // The second socket is used for the second attempt of transaction 2.
8445
8446 // The response of transaction 2.
8447 MockRead data_reads2[] = {
8448 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8449 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068450 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518451 };
8452 // The mock write results of the second attempt of transaction 2.
8453 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068454 MockWrite(SYNCHRONOUS, 93), // POST
8455 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518456 };
Ryan Sleevib8d7ea02018-05-07 20:01:018457 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518458
[email protected]bb88e1d32013-05-03 23:11:078459 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8460 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518461
thestig9d3bb0c2015-01-24 00:49:518462 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518463 "hello world", "welcome"
8464 };
8465
8466 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168467 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518468
[email protected]49639fa2011-12-20 23:22:418469 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518470
tfarina42834112016-09-22 13:38:208471 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018472 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518473
8474 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018475 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518476
bnc691fda62016-08-12 00:43:168477 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528478 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518479
wezca1070932016-05-26 20:30:528480 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518481 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8482
8483 std::string response_data;
bnc691fda62016-08-12 00:43:168484 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018485 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518486 EXPECT_EQ(kExpectedResponseData[i], response_data);
8487 }
8488}
[email protected]f9ee6b52008-11-08 06:46:238489
8490// Test the request-challenge-retry sequence for basic auth when there is
8491// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168492// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018493TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428494 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238495 request.method = "GET";
bncce36dca22015-04-21 22:11:238496 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418497 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108498 request.traffic_annotation =
8499 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298500
danakj1fd259a02016-04-16 03:17:098501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168502 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278503
[email protected]a97cca42009-08-14 01:00:298504 // The password contains an escaped character -- for this test to pass it
8505 // will need to be unescaped by HttpNetworkTransaction.
8506 EXPECT_EQ("b%40r", request.url.password());
8507
[email protected]f9ee6b52008-11-08 06:46:238508 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238509 MockWrite(
8510 "GET / HTTP/1.1\r\n"
8511 "Host: www.example.org\r\n"
8512 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238513 };
8514
8515 MockRead data_reads1[] = {
8516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8517 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8518 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068519 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238520 };
8521
[email protected]2262e3a2012-05-22 16:08:168522 // After the challenge above, the transaction will be restarted using the
8523 // identity from the url (foo, b@r) to answer the challenge.
8524 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238525 MockWrite(
8526 "GET / HTTP/1.1\r\n"
8527 "Host: www.example.org\r\n"
8528 "Connection: keep-alive\r\n"
8529 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168530 };
8531
8532 MockRead data_reads2[] = {
8533 MockRead("HTTP/1.0 200 OK\r\n"),
8534 MockRead("Content-Length: 100\r\n\r\n"),
8535 MockRead(SYNCHRONOUS, OK),
8536 };
8537
Ryan Sleevib8d7ea02018-05-07 20:01:018538 StaticSocketDataProvider data1(data_reads1, data_writes1);
8539 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078540 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8541 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238542
[email protected]49639fa2011-12-20 23:22:418543 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208544 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238546 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018547 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168548 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168549
8550 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168551 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018552 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168553 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018554 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168555 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228556
bnc691fda62016-08-12 00:43:168557 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528558 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168559
8560 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588561 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168562
8563 EXPECT_EQ(100, response->headers->GetContentLength());
8564
8565 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558566 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168567}
8568
8569// Test the request-challenge-retry sequence for basic auth when there is an
8570// incorrect identity in the URL. The identity from the URL should be used only
8571// once.
bncd16676a2016-07-20 16:23:018572TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168573 HttpRequestInfo request;
8574 request.method = "GET";
8575 // Note: the URL has a username:password in it. The password "baz" is
8576 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238577 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168578
8579 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108580 request.traffic_annotation =
8581 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168582
danakj1fd259a02016-04-16 03:17:098583 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168584 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168585
8586 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238587 MockWrite(
8588 "GET / HTTP/1.1\r\n"
8589 "Host: www.example.org\r\n"
8590 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168591 };
8592
8593 MockRead data_reads1[] = {
8594 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8595 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8596 MockRead("Content-Length: 10\r\n\r\n"),
8597 MockRead(SYNCHRONOUS, ERR_FAILED),
8598 };
8599
8600 // After the challenge above, the transaction will be restarted using the
8601 // identity from the url (foo, baz) to answer the challenge.
8602 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238603 MockWrite(
8604 "GET / HTTP/1.1\r\n"
8605 "Host: www.example.org\r\n"
8606 "Connection: keep-alive\r\n"
8607 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168608 };
8609
8610 MockRead data_reads2[] = {
8611 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8612 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8613 MockRead("Content-Length: 10\r\n\r\n"),
8614 MockRead(SYNCHRONOUS, ERR_FAILED),
8615 };
8616
8617 // After the challenge above, the transaction will be restarted using the
8618 // identity supplied by the user (foo, bar) to answer the challenge.
8619 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238620 MockWrite(
8621 "GET / HTTP/1.1\r\n"
8622 "Host: www.example.org\r\n"
8623 "Connection: keep-alive\r\n"
8624 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168625 };
8626
8627 MockRead data_reads3[] = {
8628 MockRead("HTTP/1.0 200 OK\r\n"),
8629 MockRead("Content-Length: 100\r\n\r\n"),
8630 MockRead(SYNCHRONOUS, OK),
8631 };
8632
Ryan Sleevib8d7ea02018-05-07 20:01:018633 StaticSocketDataProvider data1(data_reads1, data_writes1);
8634 StaticSocketDataProvider data2(data_reads2, data_writes2);
8635 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078636 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8637 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8638 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168639
8640 TestCompletionCallback callback1;
8641
tfarina42834112016-09-22 13:38:208642 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018643 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168644
8645 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018646 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168647
bnc691fda62016-08-12 00:43:168648 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168649 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168650 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018651 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168652 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018653 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168654 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168655
bnc691fda62016-08-12 00:43:168656 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528657 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588658 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168659
8660 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168661 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018662 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168663 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018664 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168665 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168666
bnc691fda62016-08-12 00:43:168667 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528668 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168669
8670 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588671 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168672
8673 EXPECT_EQ(100, response->headers->GetContentLength());
8674
[email protected]ea9dc9a2009-09-05 00:43:328675 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558676 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328677}
8678
[email protected]2217aa22013-10-11 03:03:548679
8680// Test the request-challenge-retry sequence for basic auth when there is a
8681// correct identity in the URL, but its use is being suppressed. The identity
8682// from the URL should never be used.
bncd16676a2016-07-20 16:23:018683TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548684 HttpRequestInfo request;
8685 request.method = "GET";
bncce36dca22015-04-21 22:11:238686 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548687 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:108688 request.traffic_annotation =
8689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548690
danakj1fd259a02016-04-16 03:17:098691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548693
8694 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238695 MockWrite(
8696 "GET / HTTP/1.1\r\n"
8697 "Host: www.example.org\r\n"
8698 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548699 };
8700
8701 MockRead data_reads1[] = {
8702 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8703 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8704 MockRead("Content-Length: 10\r\n\r\n"),
8705 MockRead(SYNCHRONOUS, ERR_FAILED),
8706 };
8707
8708 // After the challenge above, the transaction will be restarted using the
8709 // identity supplied by the user, not the one in the URL, to answer the
8710 // challenge.
8711 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238712 MockWrite(
8713 "GET / HTTP/1.1\r\n"
8714 "Host: www.example.org\r\n"
8715 "Connection: keep-alive\r\n"
8716 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548717 };
8718
8719 MockRead data_reads3[] = {
8720 MockRead("HTTP/1.0 200 OK\r\n"),
8721 MockRead("Content-Length: 100\r\n\r\n"),
8722 MockRead(SYNCHRONOUS, OK),
8723 };
8724
Ryan Sleevib8d7ea02018-05-07 20:01:018725 StaticSocketDataProvider data1(data_reads1, data_writes1);
8726 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548727 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8728 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8729
8730 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208731 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018732 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548733 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018734 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168735 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548736
bnc691fda62016-08-12 00:43:168737 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528738 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588739 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548740
8741 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168742 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018743 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548744 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018745 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168746 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548747
bnc691fda62016-08-12 00:43:168748 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528749 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548750
8751 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588752 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548753 EXPECT_EQ(100, response->headers->GetContentLength());
8754
8755 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558756 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548757}
8758
[email protected]f9ee6b52008-11-08 06:46:238759// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018760TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098761 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238762
8763 // Transaction 1: authenticate (foo, bar) on MyRealm1
8764 {
[email protected]1c773ea12009-04-28 19:58:428765 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238766 request.method = "GET";
bncce36dca22015-04-21 22:11:238767 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:108768 request.traffic_annotation =
8769 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238770
bnc691fda62016-08-12 00:43:168771 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278772
[email protected]f9ee6b52008-11-08 06:46:238773 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238774 MockWrite(
8775 "GET /x/y/z HTTP/1.1\r\n"
8776 "Host: www.example.org\r\n"
8777 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238778 };
8779
8780 MockRead data_reads1[] = {
8781 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8782 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8783 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068784 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238785 };
8786
8787 // Resend with authorization (username=foo, password=bar)
8788 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238789 MockWrite(
8790 "GET /x/y/z HTTP/1.1\r\n"
8791 "Host: www.example.org\r\n"
8792 "Connection: keep-alive\r\n"
8793 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238794 };
8795
8796 // Sever accepts the authorization.
8797 MockRead data_reads2[] = {
8798 MockRead("HTTP/1.0 200 OK\r\n"),
8799 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068800 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238801 };
8802
Ryan Sleevib8d7ea02018-05-07 20:01:018803 StaticSocketDataProvider data1(data_reads1, data_writes1);
8804 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078805 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238807
[email protected]49639fa2011-12-20 23:22:418808 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238809
tfarina42834112016-09-22 13:38:208810 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238812
8813 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018814 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238815
bnc691fda62016-08-12 00:43:168816 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528817 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588818 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238819
[email protected]49639fa2011-12-20 23:22:418820 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238821
bnc691fda62016-08-12 00:43:168822 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8823 callback2.callback());
robpercival214763f2016-07-01 23:27:018824 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238825
8826 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018827 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238828
bnc691fda62016-08-12 00:43:168829 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528830 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588831 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238832 EXPECT_EQ(100, response->headers->GetContentLength());
8833 }
8834
8835 // ------------------------------------------------------------------------
8836
8837 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
8838 {
[email protected]1c773ea12009-04-28 19:58:428839 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238840 request.method = "GET";
8841 // Note that Transaction 1 was at /x/y/z, so this is in the same
8842 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:238843 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:108844 request.traffic_annotation =
8845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238846
bnc691fda62016-08-12 00:43:168847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278848
[email protected]f9ee6b52008-11-08 06:46:238849 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238850 MockWrite(
8851 "GET /x/y/a/b HTTP/1.1\r\n"
8852 "Host: www.example.org\r\n"
8853 "Connection: keep-alive\r\n"
8854 // Send preemptive authorization for MyRealm1
8855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238856 };
8857
8858 // The server didn't like the preemptive authorization, and
8859 // challenges us for a different realm (MyRealm2).
8860 MockRead data_reads1[] = {
8861 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8862 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
8863 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068864 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238865 };
8866
8867 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
8868 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238869 MockWrite(
8870 "GET /x/y/a/b HTTP/1.1\r\n"
8871 "Host: www.example.org\r\n"
8872 "Connection: keep-alive\r\n"
8873 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238874 };
8875
8876 // Sever accepts the authorization.
8877 MockRead data_reads2[] = {
8878 MockRead("HTTP/1.0 200 OK\r\n"),
8879 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068880 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238881 };
8882
Ryan Sleevib8d7ea02018-05-07 20:01:018883 StaticSocketDataProvider data1(data_reads1, data_writes1);
8884 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078885 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8886 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238887
[email protected]49639fa2011-12-20 23:22:418888 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238889
tfarina42834112016-09-22 13:38:208890 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018891 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238892
8893 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018894 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238895
bnc691fda62016-08-12 00:43:168896 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528897 ASSERT_TRUE(response);
8898 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:048899 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:438900 EXPECT_EQ("http://www.example.org",
8901 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:048902 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:198903 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:238904
[email protected]49639fa2011-12-20 23:22:418905 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238906
bnc691fda62016-08-12 00:43:168907 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8908 callback2.callback());
robpercival214763f2016-07-01 23:27:018909 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238910
8911 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018912 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238913
bnc691fda62016-08-12 00:43:168914 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528915 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588916 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238917 EXPECT_EQ(100, response->headers->GetContentLength());
8918 }
8919
8920 // ------------------------------------------------------------------------
8921
8922 // Transaction 3: Resend a request in MyRealm's protection space --
8923 // succeed with preemptive authorization.
8924 {
[email protected]1c773ea12009-04-28 19:58:428925 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238926 request.method = "GET";
bncce36dca22015-04-21 22:11:238927 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:108928 request.traffic_annotation =
8929 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238930
bnc691fda62016-08-12 00:43:168931 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278932
[email protected]f9ee6b52008-11-08 06:46:238933 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238934 MockWrite(
8935 "GET /x/y/z2 HTTP/1.1\r\n"
8936 "Host: www.example.org\r\n"
8937 "Connection: keep-alive\r\n"
8938 // The authorization for MyRealm1 gets sent preemptively
8939 // (since the url is in the same protection space)
8940 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238941 };
8942
8943 // Sever accepts the preemptive authorization
8944 MockRead data_reads1[] = {
8945 MockRead("HTTP/1.0 200 OK\r\n"),
8946 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068947 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238948 };
8949
Ryan Sleevib8d7ea02018-05-07 20:01:018950 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078951 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:238952
[email protected]49639fa2011-12-20 23:22:418953 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238954
tfarina42834112016-09-22 13:38:208955 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018956 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238957
8958 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018959 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238960
bnc691fda62016-08-12 00:43:168961 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528962 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:238963
Emily Starkf2c9bbd2019-04-09 17:08:588964 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238965 EXPECT_EQ(100, response->headers->GetContentLength());
8966 }
8967
8968 // ------------------------------------------------------------------------
8969
8970 // Transaction 4: request another URL in MyRealm (however the
8971 // url is not known to belong to the protection space, so no pre-auth).
8972 {
[email protected]1c773ea12009-04-28 19:58:428973 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238974 request.method = "GET";
bncce36dca22015-04-21 22:11:238975 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:108976 request.traffic_annotation =
8977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238978
bnc691fda62016-08-12 00:43:168979 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278980
[email protected]f9ee6b52008-11-08 06:46:238981 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238982 MockWrite(
8983 "GET /x/1 HTTP/1.1\r\n"
8984 "Host: www.example.org\r\n"
8985 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238986 };
8987
8988 MockRead data_reads1[] = {
8989 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8990 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8991 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068992 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238993 };
8994
8995 // Resend with authorization from MyRealm's cache.
8996 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238997 MockWrite(
8998 "GET /x/1 HTTP/1.1\r\n"
8999 "Host: www.example.org\r\n"
9000 "Connection: keep-alive\r\n"
9001 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239002 };
9003
9004 // Sever accepts the authorization.
9005 MockRead data_reads2[] = {
9006 MockRead("HTTP/1.0 200 OK\r\n"),
9007 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069008 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239009 };
9010
Ryan Sleevib8d7ea02018-05-07 20:01:019011 StaticSocketDataProvider data1(data_reads1, data_writes1);
9012 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079013 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9014 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239015
[email protected]49639fa2011-12-20 23:22:419016 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239017
tfarina42834112016-09-22 13:38:209018 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019019 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239020
9021 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019022 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239023
bnc691fda62016-08-12 00:43:169024 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419025 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169026 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019027 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229028 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019029 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169030 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229031
bnc691fda62016-08-12 00:43:169032 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529033 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589034 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239035 EXPECT_EQ(100, response->headers->GetContentLength());
9036 }
9037
9038 // ------------------------------------------------------------------------
9039
9040 // Transaction 5: request a URL in MyRealm, but the server rejects the
9041 // cached identity. Should invalidate and re-prompt.
9042 {
[email protected]1c773ea12009-04-28 19:58:429043 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239044 request.method = "GET";
bncce36dca22015-04-21 22:11:239045 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109046 request.traffic_annotation =
9047 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239048
bnc691fda62016-08-12 00:43:169049 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279050
[email protected]f9ee6b52008-11-08 06:46:239051 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239052 MockWrite(
9053 "GET /p/q/t HTTP/1.1\r\n"
9054 "Host: www.example.org\r\n"
9055 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239056 };
9057
9058 MockRead data_reads1[] = {
9059 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9060 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9061 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069062 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239063 };
9064
9065 // Resend with authorization from cache for MyRealm.
9066 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239067 MockWrite(
9068 "GET /p/q/t HTTP/1.1\r\n"
9069 "Host: www.example.org\r\n"
9070 "Connection: keep-alive\r\n"
9071 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239072 };
9073
9074 // Sever rejects the authorization.
9075 MockRead data_reads2[] = {
9076 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9078 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069079 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239080 };
9081
9082 // At this point we should prompt for new credentials for MyRealm.
9083 // Restart with username=foo3, password=foo4.
9084 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239085 MockWrite(
9086 "GET /p/q/t HTTP/1.1\r\n"
9087 "Host: www.example.org\r\n"
9088 "Connection: keep-alive\r\n"
9089 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239090 };
9091
9092 // Sever accepts the authorization.
9093 MockRead data_reads3[] = {
9094 MockRead("HTTP/1.0 200 OK\r\n"),
9095 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069096 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239097 };
9098
Ryan Sleevib8d7ea02018-05-07 20:01:019099 StaticSocketDataProvider data1(data_reads1, data_writes1);
9100 StaticSocketDataProvider data2(data_reads2, data_writes2);
9101 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079102 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9103 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9104 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239105
[email protected]49639fa2011-12-20 23:22:419106 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239107
tfarina42834112016-09-22 13:38:209108 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019109 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239110
9111 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019112 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239113
bnc691fda62016-08-12 00:43:169114 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419115 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169116 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019117 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229118 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019119 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169120 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229121
bnc691fda62016-08-12 00:43:169122 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529123 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589124 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239125
[email protected]49639fa2011-12-20 23:22:419126 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239127
bnc691fda62016-08-12 00:43:169128 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9129 callback3.callback());
robpercival214763f2016-07-01 23:27:019130 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239131
[email protected]0757e7702009-03-27 04:00:229132 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019133 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239134
bnc691fda62016-08-12 00:43:169135 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529136 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589137 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239138 EXPECT_EQ(100, response->headers->GetContentLength());
9139 }
9140}
[email protected]89ceba9a2009-03-21 03:46:069141
[email protected]3c32c5f2010-05-18 15:18:129142// Tests that nonce count increments when multiple auth attempts
9143// are started with the same nonce.
bncd16676a2016-07-20 16:23:019144TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449145 HttpAuthHandlerDigest::Factory* digest_factory =
9146 new HttpAuthHandlerDigest::Factory();
9147 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9148 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9149 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079150 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099151 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129152
9153 // Transaction 1: authenticate (foo, bar) on MyRealm1
9154 {
[email protected]3c32c5f2010-05-18 15:18:129155 HttpRequestInfo request;
9156 request.method = "GET";
bncce36dca22015-04-21 22:11:239157 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109158 request.traffic_annotation =
9159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129160
bnc691fda62016-08-12 00:43:169161 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279162
[email protected]3c32c5f2010-05-18 15:18:129163 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239164 MockWrite(
9165 "GET /x/y/z HTTP/1.1\r\n"
9166 "Host: www.example.org\r\n"
9167 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129168 };
9169
9170 MockRead data_reads1[] = {
9171 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9172 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9173 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069174 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129175 };
9176
9177 // Resend with authorization (username=foo, password=bar)
9178 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239179 MockWrite(
9180 "GET /x/y/z HTTP/1.1\r\n"
9181 "Host: www.example.org\r\n"
9182 "Connection: keep-alive\r\n"
9183 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9184 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9185 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9186 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129187 };
9188
9189 // Sever accepts the authorization.
9190 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089191 MockRead("HTTP/1.0 200 OK\r\n"),
9192 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129193 };
9194
Ryan Sleevib8d7ea02018-05-07 20:01:019195 StaticSocketDataProvider data1(data_reads1, data_writes1);
9196 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9198 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129199
[email protected]49639fa2011-12-20 23:22:419200 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129201
tfarina42834112016-09-22 13:38:209202 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019203 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129204
9205 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019206 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129207
bnc691fda62016-08-12 00:43:169208 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529209 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589210 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129211
[email protected]49639fa2011-12-20 23:22:419212 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129213
bnc691fda62016-08-12 00:43:169214 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9215 callback2.callback());
robpercival214763f2016-07-01 23:27:019216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129217
9218 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019219 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129220
bnc691fda62016-08-12 00:43:169221 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529222 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589223 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129224 }
9225
9226 // ------------------------------------------------------------------------
9227
9228 // Transaction 2: Request another resource in digestive's protection space.
9229 // This will preemptively add an Authorization header which should have an
9230 // "nc" value of 2 (as compared to 1 in the first use.
9231 {
[email protected]3c32c5f2010-05-18 15:18:129232 HttpRequestInfo request;
9233 request.method = "GET";
9234 // Note that Transaction 1 was at /x/y/z, so this is in the same
9235 // protection space as digest.
bncce36dca22015-04-21 22:11:239236 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109237 request.traffic_annotation =
9238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129239
bnc691fda62016-08-12 00:43:169240 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279241
[email protected]3c32c5f2010-05-18 15:18:129242 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239243 MockWrite(
9244 "GET /x/y/a/b HTTP/1.1\r\n"
9245 "Host: www.example.org\r\n"
9246 "Connection: keep-alive\r\n"
9247 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9248 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9249 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9250 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129251 };
9252
9253 // Sever accepts the authorization.
9254 MockRead data_reads1[] = {
9255 MockRead("HTTP/1.0 200 OK\r\n"),
9256 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069257 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129258 };
9259
Ryan Sleevib8d7ea02018-05-07 20:01:019260 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079261 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129262
[email protected]49639fa2011-12-20 23:22:419263 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129264
tfarina42834112016-09-22 13:38:209265 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129267
9268 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019269 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129270
bnc691fda62016-08-12 00:43:169271 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529272 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589273 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129274 }
9275}
9276
[email protected]89ceba9a2009-03-21 03:46:069277// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019278TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069279 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099280 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169281 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069282
9283 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449284 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169285 trans.read_buf_len_ = 15;
9286 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069287
9288 // Setup state in response_
bnc691fda62016-08-12 00:43:169289 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589290 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089291 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579292 response->response_time = base::Time::Now();
9293 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069294
9295 { // Setup state for response_.vary_data
9296 HttpRequestInfo request;
9297 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9298 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279299 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439300 request.extra_headers.SetHeader("Foo", "1");
9301 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509302 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069303 }
9304
9305 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169306 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069307
9308 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169309 EXPECT_FALSE(trans.read_buf_);
9310 EXPECT_EQ(0, trans.read_buf_len_);
9311 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589312 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529313 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049314 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089315 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579316 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069317}
9318
[email protected]bacff652009-03-31 17:50:339319// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019320TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339321 HttpRequestInfo request;
9322 request.method = "GET";
bncce36dca22015-04-21 22:11:239323 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109324 request.traffic_annotation =
9325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339326
danakj1fd259a02016-04-16 03:17:099327 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169328 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279329
[email protected]bacff652009-03-31 17:50:339330 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239331 MockWrite(
9332 "GET / HTTP/1.1\r\n"
9333 "Host: www.example.org\r\n"
9334 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339335 };
9336
9337 MockRead data_reads[] = {
9338 MockRead("HTTP/1.0 200 OK\r\n"),
9339 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9340 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069341 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339342 };
9343
[email protected]5ecc992a42009-11-11 01:41:599344 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019345 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069346 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9347 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339348
[email protected]bb88e1d32013-05-03 23:11:079349 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9350 session_deps_.socket_factory->AddSocketDataProvider(&data);
9351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9352 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339353
[email protected]49639fa2011-12-20 23:22:419354 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339355
tfarina42834112016-09-22 13:38:209356 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019357 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339358
9359 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019360 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339361
bnc691fda62016-08-12 00:43:169362 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019363 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339364
9365 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019366 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339367
bnc691fda62016-08-12 00:43:169368 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339369
wezca1070932016-05-26 20:30:529370 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339371 EXPECT_EQ(100, response->headers->GetContentLength());
9372}
9373
9374// Test HTTPS connections to a site with a bad certificate, going through a
9375// proxy
bncd16676a2016-07-20 16:23:019376TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499377 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9378 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339379
9380 HttpRequestInfo request;
9381 request.method = "GET";
bncce36dca22015-04-21 22:11:239382 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109383 request.traffic_annotation =
9384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339385
9386 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179387 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9388 "Host: www.example.org:443\r\n"
9389 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339390 };
9391
9392 MockRead proxy_reads[] = {
9393 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069394 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339395 };
9396
9397 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179398 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9399 "Host: www.example.org:443\r\n"
9400 "Proxy-Connection: keep-alive\r\n\r\n"),
9401 MockWrite("GET / HTTP/1.1\r\n"
9402 "Host: www.example.org\r\n"
9403 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339404 };
9405
9406 MockRead data_reads[] = {
9407 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9408 MockRead("HTTP/1.0 200 OK\r\n"),
9409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9410 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069411 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339412 };
9413
Ryan Sleevib8d7ea02018-05-07 20:01:019414 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9415 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069416 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9417 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339418
[email protected]bb88e1d32013-05-03 23:11:079419 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9420 session_deps_.socket_factory->AddSocketDataProvider(&data);
9421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339423
[email protected]49639fa2011-12-20 23:22:419424 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339425
9426 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079427 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339428
danakj1fd259a02016-04-16 03:17:099429 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169430 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339431
tfarina42834112016-09-22 13:38:209432 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019433 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339434
9435 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019436 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339437
bnc691fda62016-08-12 00:43:169438 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019439 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339440
9441 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019442 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339443
bnc691fda62016-08-12 00:43:169444 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339445
wezca1070932016-05-26 20:30:529446 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339447 EXPECT_EQ(100, response->headers->GetContentLength());
9448 }
9449}
9450
[email protected]2df19bb2010-08-25 20:13:469451
9452// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019453TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599454 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499455 ProxyResolutionService::CreateFixedFromPacResult(
9456 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519457 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079458 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469459
9460 HttpRequestInfo request;
9461 request.method = "GET";
bncce36dca22015-04-21 22:11:239462 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109463 request.traffic_annotation =
9464 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469465
9466 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179467 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9468 "Host: www.example.org:443\r\n"
9469 "Proxy-Connection: keep-alive\r\n\r\n"),
9470 MockWrite("GET / HTTP/1.1\r\n"
9471 "Host: www.example.org\r\n"
9472 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469473 };
9474
9475 MockRead data_reads[] = {
9476 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9477 MockRead("HTTP/1.1 200 OK\r\n"),
9478 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9479 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069480 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469481 };
9482
Ryan Sleevib8d7ea02018-05-07 20:01:019483 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069484 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9485 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469486
[email protected]bb88e1d32013-05-03 23:11:079487 session_deps_.socket_factory->AddSocketDataProvider(&data);
9488 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9489 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469490
[email protected]49639fa2011-12-20 23:22:419491 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469492
danakj1fd259a02016-04-16 03:17:099493 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169494 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469495
tfarina42834112016-09-22 13:38:209496 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019497 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469498
9499 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019500 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169501 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469502
wezca1070932016-05-26 20:30:529503 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469504
tbansal2ecbbc72016-10-06 17:15:479505 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469506 EXPECT_TRUE(response->headers->IsKeepAlive());
9507 EXPECT_EQ(200, response->headers->response_code());
9508 EXPECT_EQ(100, response->headers->GetContentLength());
9509 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209510
9511 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169512 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209513 TestLoadTimingNotReusedWithPac(load_timing_info,
9514 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469515}
9516
Eric Roman695a7872019-04-16 21:53:299517// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019518TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599519 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499520 ProxyResolutionService::CreateFixedFromPacResult(
9521 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519522 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079523 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299524
Matt Menkeecfecfc72019-02-05 19:15:289525 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9526 session_deps_.host_resolver->set_ondemand_mode(true);
9527
[email protected]511f6f52010-12-17 03:58:299528 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129529 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299530 request.method = "GET";
bncce36dca22015-04-21 22:11:239531 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109532 request.traffic_annotation =
9533 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299534
9535 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289536 MockWrite(ASYNC, 0,
9537 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179538 "Host: www.example.org:443\r\n"
9539 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299540 };
9541
9542 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289543 // Pause on first read.
9544 MockRead(ASYNC, ERR_IO_PENDING, 1),
9545 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9546 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9547 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299548 };
9549
Matt Menkeecfecfc72019-02-05 19:15:289550 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069551 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299552
[email protected]bb88e1d32013-05-03 23:11:079553 session_deps_.socket_factory->AddSocketDataProvider(&data);
9554 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299555
[email protected]49639fa2011-12-20 23:22:419556 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299557
danakj1fd259a02016-04-16 03:17:099558 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169559 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299560
tfarina42834112016-09-22 13:38:209561 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289563 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9564
9565 // Host resolution takes |kTimeIncrement|.
9566 FastForwardBy(kTimeIncrement);
9567 // Resolving the current request with |ResolveNow| will cause the pending
9568 // request to instantly complete, and the async connect will start as well.
9569 session_deps_.host_resolver->ResolveOnlyRequestNow();
9570
9571 // Connecting takes |kTimeIncrement|.
9572 FastForwardBy(kTimeIncrement);
9573 data.RunUntilPaused();
9574
9575 // The server takes |kTimeIncrement| to respond.
9576 FastForwardBy(kTimeIncrement);
9577 data.Resume();
[email protected]511f6f52010-12-17 03:58:299578
9579 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599580 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299581}
9582
Eric Roman74103c72019-02-21 00:23:129583// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9584TEST_F(HttpNetworkTransactionTest,
9585 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9586 base::HistogramTester histograms;
9587 session_deps_.proxy_resolution_service =
9588 ProxyResolutionService::CreateFixedFromPacResult(
9589 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9590 TestNetLog net_log;
9591 session_deps_.net_log = &net_log;
9592
9593 HttpRequestInfo request;
9594 request.method = "GET";
9595 request.url = GURL("https://www.example.org/");
9596 request.traffic_annotation =
9597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9598
9599 MockWrite data_writes[] = {
9600 MockWrite(ASYNC, 0,
9601 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9602 "Host: www.example.org:443\r\n"
9603 "Proxy-Connection: keep-alive\r\n\r\n"),
9604 };
9605
9606 MockRead data_reads[] = {
9607 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9608 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9609 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9610 };
9611
9612 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9613 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9614
9615 session_deps_.socket_factory->AddSocketDataProvider(&data);
9616 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9617
9618 TestCompletionCallback callback;
9619
9620 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9621 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9622
9623 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9624 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9625
9626 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599627 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129628}
9629
9630// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9631// request for main frames.
9632TEST_F(HttpNetworkTransactionTest,
9633 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9634 base::HistogramTester histograms;
9635 session_deps_.proxy_resolution_service =
9636 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9637 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9638 TestNetLog net_log;
9639 session_deps_.net_log = &net_log;
9640
9641 HttpRequestInfo request;
9642 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9643 request.method = "GET";
9644 request.url = GURL("https://www.example.org/");
9645 request.traffic_annotation =
9646 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9647
9648 MockWrite data_writes[] = {
9649 MockWrite(ASYNC, 0,
9650 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9651 "Host: www.example.org:443\r\n"
9652 "Proxy-Connection: keep-alive\r\n\r\n"),
9653 };
9654
9655 MockRead data_reads[] = {
9656 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9657 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9658 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9659 };
9660
9661 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9662 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9663
9664 session_deps_.socket_factory->AddSocketDataProvider(&data);
9665 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9666
9667 TestCompletionCallback callback;
9668
9669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9670 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9671
9672 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9673 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9674
9675 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599676 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129677}
9678
Eric Roman695a7872019-04-16 21:53:299679// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129680// frames.
bncd16676a2016-07-20 16:23:019681TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129682 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499683 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9684 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289685 TestNetLog net_log;
9686 session_deps_.net_log = &net_log;
9687
Matt Menkeecfecfc72019-02-05 19:15:289688 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9689 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299690
9691 HttpRequestInfo request;
9692 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129693 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239694 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109695 request.traffic_annotation =
9696 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299697
Ryan Hamilton0239aac2018-05-19 00:03:139698 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049699 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9700 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139701 spdy::SpdySerializedFrame goaway(
9702 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299703 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419704 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289705 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299706 };
9707
9708 static const char* const kExtraHeaders[] = {
9709 "location",
9710 "http://login.example.com/",
9711 };
Ryan Hamilton0239aac2018-05-19 00:03:139712 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249713 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299714 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289715 // Pause on first read.
9716 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9717 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299718 };
9719
Matt Menkeecfecfc72019-02-05 19:15:289720 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069721 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369722 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299723
[email protected]bb88e1d32013-05-03 23:11:079724 session_deps_.socket_factory->AddSocketDataProvider(&data);
9725 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299726
[email protected]49639fa2011-12-20 23:22:419727 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299728
danakj1fd259a02016-04-16 03:17:099729 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169730 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299731
tfarina42834112016-09-22 13:38:209732 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019733 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289734 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299735
Matt Menkeecfecfc72019-02-05 19:15:289736 // Host resolution takes |kTimeIncrement|.
9737 FastForwardBy(kTimeIncrement);
9738 // Resolving the current request with |ResolveNow| will cause the pending
9739 // request to instantly complete, and the async connect will start as well.
9740 session_deps_.host_resolver->ResolveOnlyRequestNow();
9741
9742 // Connecting takes |kTimeIncrement|.
9743 FastForwardBy(kTimeIncrement);
9744 data.RunUntilPaused();
9745
9746 FastForwardBy(kTimeIncrement);
9747 data.Resume();
[email protected]511f6f52010-12-17 03:58:299748 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599749 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299750}
9751
[email protected]4eddbc732012-08-09 05:40:179752// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019753TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499754 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9755 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299756
9757 HttpRequestInfo request;
9758 request.method = "GET";
bncce36dca22015-04-21 22:11:239759 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109760 request.traffic_annotation =
9761 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299762
9763 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179764 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9765 "Host: www.example.org:443\r\n"
9766 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299767 };
9768
9769 MockRead data_reads[] = {
9770 MockRead("HTTP/1.1 404 Not Found\r\n"),
9771 MockRead("Content-Length: 23\r\n\r\n"),
9772 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069773 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299774 };
9775
Ryan Sleevib8d7ea02018-05-07 20:01:019776 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069777 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299778
[email protected]bb88e1d32013-05-03 23:11:079779 session_deps_.socket_factory->AddSocketDataProvider(&data);
9780 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299781
[email protected]49639fa2011-12-20 23:22:419782 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299783
danakj1fd259a02016-04-16 03:17:099784 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299786
tfarina42834112016-09-22 13:38:209787 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019788 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299789
9790 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019791 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299792
ttuttle960fcbf2016-04-19 13:26:329793 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299794}
9795
[email protected]4eddbc732012-08-09 05:40:179796// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019797TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499798 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9799 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299800
9801 HttpRequestInfo request;
9802 request.method = "GET";
bncce36dca22015-04-21 22:11:239803 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109804 request.traffic_annotation =
9805 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299806
Ryan Hamilton0239aac2018-05-19 00:03:139807 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049808 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9809 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139810 spdy::SpdySerializedFrame rst(
9811 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299812 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419813 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299814 };
9815
9816 static const char* const kExtraHeaders[] = {
9817 "location",
9818 "http://login.example.com/",
9819 };
Ryan Hamilton0239aac2018-05-19 00:03:139820 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249821 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139822 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199823 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299824 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419825 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:139826 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299827 };
9828
Ryan Sleevib8d7ea02018-05-07 20:01:019829 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069830 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369831 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299832
[email protected]bb88e1d32013-05-03 23:11:079833 session_deps_.socket_factory->AddSocketDataProvider(&data);
9834 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299835
[email protected]49639fa2011-12-20 23:22:419836 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299837
danakj1fd259a02016-04-16 03:17:099838 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169839 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299840
tfarina42834112016-09-22 13:38:209841 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019842 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299843
9844 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019845 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299846
ttuttle960fcbf2016-04-19 13:26:329847 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299848}
9849
[email protected]0c5fb722012-02-28 11:50:359850// Test the request-challenge-retry sequence for basic auth, through
9851// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:019852TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:359853 HttpRequestInfo request;
9854 request.method = "GET";
bncce36dca22015-04-21 22:11:239855 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:359856 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:299857 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:109858 request.traffic_annotation =
9859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:359860
9861 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:599862 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499863 ProxyResolutionService::CreateFixedFromPacResult(
9864 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519865 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:079866 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:099867 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:359868
9869 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:139870 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049871 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9872 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139873 spdy::SpdySerializedFrame rst(
9874 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:389875 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:359876
bnc691fda62016-08-12 00:43:169877 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:359878 // be issuing -- the final header line contains the credentials.
9879 const char* const kAuthCredentials[] = {
9880 "proxy-authorization", "Basic Zm9vOmJhcg==",
9881 };
Ryan Hamilton0239aac2018-05-19 00:03:139882 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049883 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
9884 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:239885 HostPortPair("www.example.org", 443)));
9886 // fetch https://www.example.org/ via HTTP
9887 const char get[] =
9888 "GET / HTTP/1.1\r\n"
9889 "Host: www.example.org\r\n"
9890 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:139891 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:199892 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:359893
9894 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:419895 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
9896 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:359897 };
9898
9899 // The proxy responds to the connect with a 407, using a persistent
9900 // connection.
thestig9d3bb0c2015-01-24 00:49:519901 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:359902 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:359903 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
9904 };
Ryan Hamilton0239aac2018-05-19 00:03:139905 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249906 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:359907
Ryan Hamilton0239aac2018-05-19 00:03:139908 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:359909 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:359910 const char resp[] = "HTTP/1.1 200 OK\r\n"
9911 "Content-Length: 5\r\n\r\n";
9912
Ryan Hamilton0239aac2018-05-19 00:03:139913 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:199914 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:139915 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:199916 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:359917 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:419918 CreateMockRead(conn_auth_resp, 1, ASYNC),
9919 CreateMockRead(conn_resp, 4, ASYNC),
9920 CreateMockRead(wrapped_get_resp, 6, ASYNC),
9921 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:139922 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:359923 };
9924
Ryan Sleevib8d7ea02018-05-07 20:01:019925 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:079926 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:359927 // Negotiate SPDY to the proxy
9928 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:369929 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:079930 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:359931 // Vanilla SSL to the server
9932 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079933 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:359934
9935 TestCompletionCallback callback1;
9936
bnc87dcefc2017-05-25 12:47:589937 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199938 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:359939
9940 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:019941 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359942
9943 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019944 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:549945 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:359946 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:009947 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9948 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359949 ExpectLogContainsSomewhere(
9950 entries, pos,
mikecirone8b85c432016-09-08 19:11:009951 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9952 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359953
9954 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529955 ASSERT_TRUE(response);
9956 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:359957 EXPECT_EQ(407, response->headers->response_code());
9958 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:589959 EXPECT_TRUE(response->auth_challenge.has_value());
9960 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:359961
9962 TestCompletionCallback callback2;
9963
9964 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
9965 callback2.callback());
robpercival214763f2016-07-01 23:27:019966 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359967
9968 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019969 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:359970
9971 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529972 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:359973
9974 EXPECT_TRUE(response->headers->IsKeepAlive());
9975 EXPECT_EQ(200, response->headers->response_code());
9976 EXPECT_EQ(5, response->headers->GetContentLength());
9977 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9978
9979 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:589980 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:359981
[email protected]029c83b62013-01-24 05:28:209982 LoadTimingInfo load_timing_info;
9983 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9984 TestLoadTimingNotReusedWithPac(load_timing_info,
9985 CONNECT_TIMING_HAS_SSL_TIMES);
9986
[email protected]0c5fb722012-02-28 11:50:359987 trans.reset();
9988 session->CloseAllConnections();
9989}
9990
[email protected]7c6f7ba2012-04-03 04:09:299991// Test that an explicitly trusted SPDY proxy can push a resource from an
9992// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:019993TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:159994 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:199995 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:159996 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
9997 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:299998 HttpRequestInfo request;
9999 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010000 request.traffic_annotation =
10001 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910002
[email protected]7c6f7ba2012-04-03 04:09:2910003 request.method = "GET";
bncce36dca22015-04-21 22:11:2310004 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910005 push_request.method = "GET";
10006 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010007 push_request.traffic_annotation =
10008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910009
tbansal28e68f82016-02-04 02:56:1510010 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910011 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910012 ProxyResolutionService::CreateFixedFromPacResult(
10013 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110014 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710015 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010016
Eric Roman3d8546a2018-09-10 17:00:5210017 session_deps_.proxy_resolution_service->SetProxyDelegate(
10018 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010019
danakj1fd259a02016-04-16 03:17:0910020 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910021
Ryan Hamilton0239aac2018-05-19 00:03:1310022 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510023 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310024 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510025 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910026
10027 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110028 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510029 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910030 };
10031
Ryan Hamilton0239aac2018-05-19 00:03:1310032 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510033 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610034
Ryan Hamilton0239aac2018-05-19 00:03:1310035 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510036 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910037
Ryan Hamilton0239aac2018-05-19 00:03:1310038 spdy::SpdySerializedFrame stream1_body(
10039 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910040
Ryan Hamilton0239aac2018-05-19 00:03:1310041 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910042 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910043
10044 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610045 CreateMockRead(stream2_syn, 1, ASYNC),
10046 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510047 CreateMockRead(stream1_body, 4, ASYNC),
10048 CreateMockRead(stream2_body, 5, ASYNC),
10049 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910050 };
10051
Ryan Sleevib8d7ea02018-05-07 20:01:0110052 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710053 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910054 // Negotiate SPDY to the proxy
10055 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610056 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710057 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910058
bnc87dcefc2017-05-25 12:47:5810059 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910060 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910061 TestCompletionCallback callback;
10062 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910064
10065 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110066 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910067 const HttpResponseInfo* response = trans->GetResponseInfo();
10068
bnc87dcefc2017-05-25 12:47:5810069 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910070 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010071 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110072 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910073
10074 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110075 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910076 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10077
wezca1070932016-05-26 20:30:5210078 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910079 EXPECT_TRUE(response->headers->IsKeepAlive());
10080
10081 EXPECT_EQ(200, response->headers->response_code());
10082 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10083
10084 std::string response_data;
10085 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110086 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910087 EXPECT_EQ("hello!", response_data);
10088
[email protected]029c83b62013-01-24 05:28:2010089 LoadTimingInfo load_timing_info;
10090 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10091 TestLoadTimingNotReusedWithPac(load_timing_info,
10092 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10093
[email protected]7c6f7ba2012-04-03 04:09:2910094 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210095 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910096 EXPECT_EQ(200, push_response->headers->response_code());
10097
10098 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110099 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910100 EXPECT_EQ("pushed", response_data);
10101
[email protected]029c83b62013-01-24 05:28:2010102 LoadTimingInfo push_load_timing_info;
10103 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10104 TestLoadTimingReusedWithPac(push_load_timing_info);
10105 // The transactions should share a socket ID, despite being for different
10106 // origins.
10107 EXPECT_EQ(load_timing_info.socket_log_id,
10108 push_load_timing_info.socket_log_id);
10109
[email protected]7c6f7ba2012-04-03 04:09:2910110 trans.reset();
10111 push_trans.reset();
10112 session->CloseAllConnections();
10113}
10114
[email protected]8c843192012-04-05 07:15:0010115// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110116TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510117 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910118 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510119 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10120 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010121 HttpRequestInfo request;
10122
10123 request.method = "GET";
bncce36dca22015-04-21 22:11:2310124 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010125 request.traffic_annotation =
10126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010127
Ramin Halavatica8d5252018-03-12 05:33:4910128 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10129 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110130 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710131 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010132
10133 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210134 session_deps_.proxy_resolution_service->SetProxyDelegate(
10135 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010136
danakj1fd259a02016-04-16 03:17:0910137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010138
Ryan Hamilton0239aac2018-05-19 00:03:1310139 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510140 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010141
Ryan Hamilton0239aac2018-05-19 00:03:1310142 spdy::SpdySerializedFrame push_rst(
10143 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010144
10145 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110146 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010147 };
10148
Ryan Hamilton0239aac2018-05-19 00:03:1310149 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510150 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010151
Ryan Hamilton0239aac2018-05-19 00:03:1310152 spdy::SpdySerializedFrame stream1_body(
10153 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010154
Ryan Hamilton0239aac2018-05-19 00:03:1310155 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510156 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010157
10158 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110159 CreateMockRead(stream1_reply, 1, ASYNC),
10160 CreateMockRead(stream2_syn, 2, ASYNC),
10161 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910162 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010163 };
10164
Ryan Sleevib8d7ea02018-05-07 20:01:0110165 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710166 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010167 // Negotiate SPDY to the proxy
10168 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610169 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710170 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010171
bnc87dcefc2017-05-25 12:47:5810172 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910173 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010174 TestCompletionCallback callback;
10175 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110176 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010177
10178 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110179 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010180 const HttpResponseInfo* response = trans->GetResponseInfo();
10181
wezca1070932016-05-26 20:30:5210182 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010183 EXPECT_TRUE(response->headers->IsKeepAlive());
10184
10185 EXPECT_EQ(200, response->headers->response_code());
10186 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10187
10188 std::string response_data;
10189 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110190 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010191 EXPECT_EQ("hello!", response_data);
10192
10193 trans.reset();
10194 session->CloseAllConnections();
10195}
10196
tbansal8ef1d3e2016-02-03 04:05:4210197// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10198// resources.
bncd16676a2016-07-20 16:23:0110199TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510200 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910201 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510202 proxy_delegate->set_trusted_spdy_proxy(
10203 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10204
tbansal8ef1d3e2016-02-03 04:05:4210205 HttpRequestInfo request;
10206
10207 request.method = "GET";
10208 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010209 request.traffic_annotation =
10210 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210211
10212 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910213 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10214 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210215 BoundTestNetLog log;
10216 session_deps_.net_log = log.bound().net_log();
10217
10218 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210219 session_deps_.proxy_resolution_service->SetProxyDelegate(
10220 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210221
danakj1fd259a02016-04-16 03:17:0910222 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210223
Ryan Hamilton0239aac2018-05-19 00:03:1310224 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510225 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310226 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510227 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210228
10229 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110230 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510231 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210232 };
10233
Ryan Hamilton0239aac2018-05-19 00:03:1310234 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510235 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210236
Ryan Hamilton0239aac2018-05-19 00:03:1310237 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310238 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910239
Ryan Hamilton0239aac2018-05-19 00:03:1310240 spdy::SpdySerializedFrame stream1_body(
10241 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210242
Ryan Hamilton0239aac2018-05-19 00:03:1310243 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510244 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210245
Ryan Hamilton0239aac2018-05-19 00:03:1310246 spdy::SpdySerializedFrame stream2_body(
10247 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210248
10249 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110250 CreateMockRead(stream1_reply, 1, ASYNC),
10251 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510252 CreateMockRead(stream1_body, 4, ASYNC),
10253 CreateMockRead(stream2_body, 5, ASYNC),
10254 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210255 };
10256
Ryan Sleevib8d7ea02018-05-07 20:01:0110257 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210258 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10259 // Negotiate SPDY to the proxy
10260 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610261 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210262 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10263
bnc87dcefc2017-05-25 12:47:5810264 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910265 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210266 TestCompletionCallback callback;
10267 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110268 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210269
10270 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110271 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210272 const HttpResponseInfo* response = trans->GetResponseInfo();
10273
wezca1070932016-05-26 20:30:5210274 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210275 EXPECT_TRUE(response->headers->IsKeepAlive());
10276
10277 EXPECT_EQ(200, response->headers->response_code());
10278 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10279
10280 std::string response_data;
10281 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110282 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210283 EXPECT_EQ("hello!", response_data);
10284
10285 trans.reset();
10286 session->CloseAllConnections();
10287}
10288
[email protected]2df19bb2010-08-25 20:13:4610289// Test HTTPS connections to a site with a bad certificate, going through an
10290// HTTPS proxy
bncd16676a2016-07-20 16:23:0110291TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910292 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10293 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610294
10295 HttpRequestInfo request;
10296 request.method = "GET";
bncce36dca22015-04-21 22:11:2310297 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010298 request.traffic_annotation =
10299 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610300
10301 // Attempt to fetch the URL from a server with a bad cert
10302 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710303 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10304 "Host: www.example.org:443\r\n"
10305 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610306 };
10307
10308 MockRead bad_cert_reads[] = {
10309 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610310 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610311 };
10312
10313 // Attempt to fetch the URL with a good cert
10314 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710315 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10316 "Host: www.example.org:443\r\n"
10317 "Proxy-Connection: keep-alive\r\n\r\n"),
10318 MockWrite("GET / HTTP/1.1\r\n"
10319 "Host: www.example.org\r\n"
10320 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610321 };
10322
10323 MockRead good_cert_reads[] = {
10324 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10325 MockRead("HTTP/1.0 200 OK\r\n"),
10326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10327 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610328 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610329 };
10330
Ryan Sleevib8d7ea02018-05-07 20:01:0110331 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10332 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610333 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10334 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610335
10336 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710337 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10338 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10339 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610340
10341 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710342 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10343 session_deps_.socket_factory->AddSocketDataProvider(&data);
10344 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610345
[email protected]49639fa2011-12-20 23:22:4110346 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610347
danakj1fd259a02016-04-16 03:17:0910348 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610349 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610350
tfarina42834112016-09-22 13:38:2010351 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110352 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610353
10354 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110355 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610356
bnc691fda62016-08-12 00:43:1610357 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610359
10360 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110361 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610362
bnc691fda62016-08-12 00:43:1610363 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610364
wezca1070932016-05-26 20:30:5210365 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610366 EXPECT_EQ(100, response->headers->GetContentLength());
10367}
10368
bncd16676a2016-07-20 16:23:0110369TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210370 HttpRequestInfo request;
10371 request.method = "GET";
bncce36dca22015-04-21 22:11:2310372 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310373 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10374 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1010375 request.traffic_annotation =
10376 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210377
danakj1fd259a02016-04-16 03:17:0910378 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610379 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710380
[email protected]1c773ea12009-04-28 19:58:4210381 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310382 MockWrite(
10383 "GET / HTTP/1.1\r\n"
10384 "Host: www.example.org\r\n"
10385 "Connection: keep-alive\r\n"
10386 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210387 };
10388
10389 // Lastly, the server responds with the actual content.
10390 MockRead data_reads[] = {
10391 MockRead("HTTP/1.0 200 OK\r\n"),
10392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10393 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610394 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210395 };
10396
Ryan Sleevib8d7ea02018-05-07 20:01:0110397 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710398 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210399
[email protected]49639fa2011-12-20 23:22:4110400 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210401
tfarina42834112016-09-22 13:38:2010402 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210404
10405 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110406 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210407}
10408
bncd16676a2016-07-20 16:23:0110409TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010410 // Test user agent values, used both for the request header of the original
10411 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10412 // no request header / no HttpUserAgentSettings object.
10413 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910414
Matt Menked732ea42019-03-08 12:05:0010415 for (const char* setting_user_agent : kTestUserAgents) {
10416 if (!setting_user_agent) {
10417 session_deps_.http_user_agent_settings.reset();
10418 } else {
10419 session_deps_.http_user_agent_settings =
10420 std::make_unique<StaticHttpUserAgentSettings>(
10421 std::string() /* accept-language */, setting_user_agent);
10422 }
10423 session_deps_.proxy_resolution_service =
10424 ProxyResolutionService::CreateFixed("myproxy:70",
10425 TRAFFIC_ANNOTATION_FOR_TESTS);
10426 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10427 for (const char* request_user_agent : kTestUserAgents) {
10428 HttpRequestInfo request;
10429 request.method = "GET";
10430 request.url = GURL("https://www.example.org/");
10431 if (request_user_agent) {
10432 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10433 request_user_agent);
10434 }
10435 request.traffic_annotation =
10436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710437
Matt Menked732ea42019-03-08 12:05:0010438 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910439
Matt Menked732ea42019-03-08 12:05:0010440 std::string expected_request;
10441 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10442 expected_request =
10443 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10444 "Host: www.example.org:443\r\n"
10445 "Proxy-Connection: keep-alive\r\n\r\n";
10446 } else {
10447 expected_request = base::StringPrintf(
10448 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10449 "Host: www.example.org:443\r\n"
10450 "Proxy-Connection: keep-alive\r\n"
10451 "User-Agent: %s\r\n\r\n",
10452 setting_user_agent);
10453 }
10454 MockWrite data_writes[] = {
10455 MockWrite(expected_request.c_str()),
10456 };
10457 MockRead data_reads[] = {
10458 // Return an error, so the transaction stops here (this test isn't
10459 // interested in the rest).
10460 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10461 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10462 MockRead("Proxy-Connection: close\r\n\r\n"),
10463 };
[email protected]da81f132010-08-18 23:39:2910464
Matt Menked732ea42019-03-08 12:05:0010465 StaticSocketDataProvider data(data_reads, data_writes);
10466 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910467
Matt Menked732ea42019-03-08 12:05:0010468 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910469
Matt Menked732ea42019-03-08 12:05:0010470 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10471 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10472
10473 rv = callback.WaitForResult();
10474 EXPECT_THAT(rv, IsOk());
10475 }
10476 }
[email protected]da81f132010-08-18 23:39:2910477}
10478
bncd16676a2016-07-20 16:23:0110479TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210480 HttpRequestInfo request;
10481 request.method = "GET";
bncce36dca22015-04-21 22:11:2310482 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610483 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10484 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1010485 request.traffic_annotation =
10486 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210487
danakj1fd259a02016-04-16 03:17:0910488 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610489 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710490
[email protected]1c773ea12009-04-28 19:58:4210491 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310492 MockWrite(
10493 "GET / HTTP/1.1\r\n"
10494 "Host: www.example.org\r\n"
10495 "Connection: keep-alive\r\n"
10496 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210497 };
10498
10499 // Lastly, the server responds with the actual content.
10500 MockRead data_reads[] = {
10501 MockRead("HTTP/1.0 200 OK\r\n"),
10502 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10503 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610504 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210505 };
10506
Ryan Sleevib8d7ea02018-05-07 20:01:0110507 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710508 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210509
[email protected]49639fa2011-12-20 23:22:4110510 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210511
tfarina42834112016-09-22 13:38:2010512 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110513 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210514
10515 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110516 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210517}
10518
bncd16676a2016-07-20 16:23:0110519TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210520 HttpRequestInfo request;
10521 request.method = "POST";
bncce36dca22015-04-21 22:11:2310522 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010523 request.traffic_annotation =
10524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210525
danakj1fd259a02016-04-16 03:17:0910526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610527 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710528
[email protected]1c773ea12009-04-28 19:58:4210529 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310530 MockWrite(
10531 "POST / HTTP/1.1\r\n"
10532 "Host: www.example.org\r\n"
10533 "Connection: keep-alive\r\n"
10534 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210535 };
10536
10537 // Lastly, the server responds with the actual content.
10538 MockRead data_reads[] = {
10539 MockRead("HTTP/1.0 200 OK\r\n"),
10540 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10541 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610542 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210543 };
10544
Ryan Sleevib8d7ea02018-05-07 20:01:0110545 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710546 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210547
[email protected]49639fa2011-12-20 23:22:4110548 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210549
tfarina42834112016-09-22 13:38:2010550 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110551 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210552
10553 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110554 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210555}
10556
bncd16676a2016-07-20 16:23:0110557TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210558 HttpRequestInfo request;
10559 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310560 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010561 request.traffic_annotation =
10562 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210563
danakj1fd259a02016-04-16 03:17:0910564 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610565 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710566
[email protected]1c773ea12009-04-28 19:58:4210567 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310568 MockWrite(
10569 "PUT / HTTP/1.1\r\n"
10570 "Host: www.example.org\r\n"
10571 "Connection: keep-alive\r\n"
10572 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210573 };
10574
10575 // Lastly, the server responds with the actual content.
10576 MockRead data_reads[] = {
10577 MockRead("HTTP/1.0 200 OK\r\n"),
10578 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10579 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610580 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210581 };
10582
Ryan Sleevib8d7ea02018-05-07 20:01:0110583 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710584 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210585
[email protected]49639fa2011-12-20 23:22:4110586 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210587
tfarina42834112016-09-22 13:38:2010588 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110589 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210590
10591 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110592 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210593}
10594
bncd16676a2016-07-20 16:23:0110595TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210596 HttpRequestInfo request;
10597 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310598 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010599 request.traffic_annotation =
10600 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210601
danakj1fd259a02016-04-16 03:17:0910602 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610603 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710604
[email protected]1c773ea12009-04-28 19:58:4210605 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310606 MockWrite("HEAD / HTTP/1.1\r\n"
10607 "Host: www.example.org\r\n"
10608 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210609 };
10610
10611 // Lastly, the server responds with the actual content.
10612 MockRead data_reads[] = {
10613 MockRead("HTTP/1.0 200 OK\r\n"),
10614 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10615 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610616 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210617 };
10618
Ryan Sleevib8d7ea02018-05-07 20:01:0110619 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710620 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210621
[email protected]49639fa2011-12-20 23:22:4110622 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210623
tfarina42834112016-09-22 13:38:2010624 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110625 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210626
10627 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110628 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210629}
10630
bncd16676a2016-07-20 16:23:0110631TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210632 HttpRequestInfo request;
10633 request.method = "GET";
bncce36dca22015-04-21 22:11:2310634 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210635 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010636 request.traffic_annotation =
10637 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210638
danakj1fd259a02016-04-16 03:17:0910639 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610640 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710641
[email protected]1c773ea12009-04-28 19:58:4210642 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310643 MockWrite(
10644 "GET / HTTP/1.1\r\n"
10645 "Host: www.example.org\r\n"
10646 "Connection: keep-alive\r\n"
10647 "Pragma: no-cache\r\n"
10648 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210649 };
10650
10651 // Lastly, the server responds with the actual content.
10652 MockRead data_reads[] = {
10653 MockRead("HTTP/1.0 200 OK\r\n"),
10654 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10655 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610656 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210657 };
10658
Ryan Sleevib8d7ea02018-05-07 20:01:0110659 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710660 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210661
[email protected]49639fa2011-12-20 23:22:4110662 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210663
tfarina42834112016-09-22 13:38:2010664 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110665 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210666
10667 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110668 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210669}
10670
bncd16676a2016-07-20 16:23:0110671TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210672 HttpRequestInfo request;
10673 request.method = "GET";
bncce36dca22015-04-21 22:11:2310674 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210675 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010676 request.traffic_annotation =
10677 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210678
danakj1fd259a02016-04-16 03:17:0910679 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610680 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710681
[email protected]1c773ea12009-04-28 19:58:4210682 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310683 MockWrite(
10684 "GET / HTTP/1.1\r\n"
10685 "Host: www.example.org\r\n"
10686 "Connection: keep-alive\r\n"
10687 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210688 };
10689
10690 // Lastly, the server responds with the actual content.
10691 MockRead data_reads[] = {
10692 MockRead("HTTP/1.0 200 OK\r\n"),
10693 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10694 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610695 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210696 };
10697
Ryan Sleevib8d7ea02018-05-07 20:01:0110698 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710699 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210700
[email protected]49639fa2011-12-20 23:22:4110701 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210702
tfarina42834112016-09-22 13:38:2010703 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110704 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210705
10706 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110707 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210708}
10709
bncd16676a2016-07-20 16:23:0110710TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210711 HttpRequestInfo request;
10712 request.method = "GET";
bncce36dca22015-04-21 22:11:2310713 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310714 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010715 request.traffic_annotation =
10716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210717
danakj1fd259a02016-04-16 03:17:0910718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610719 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710720
[email protected]1c773ea12009-04-28 19:58:4210721 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310722 MockWrite(
10723 "GET / HTTP/1.1\r\n"
10724 "Host: www.example.org\r\n"
10725 "Connection: keep-alive\r\n"
10726 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210727 };
10728
10729 // Lastly, the server responds with the actual content.
10730 MockRead data_reads[] = {
10731 MockRead("HTTP/1.0 200 OK\r\n"),
10732 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10733 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610734 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210735 };
10736
Ryan Sleevib8d7ea02018-05-07 20:01:0110737 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710738 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210739
[email protected]49639fa2011-12-20 23:22:4110740 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210741
tfarina42834112016-09-22 13:38:2010742 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110743 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210744
10745 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110746 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210747}
10748
bncd16676a2016-07-20 16:23:0110749TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710750 HttpRequestInfo request;
10751 request.method = "GET";
bncce36dca22015-04-21 22:11:2310752 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310753 request.extra_headers.SetHeader("referer", "www.foo.com");
10754 request.extra_headers.SetHeader("hEllo", "Kitty");
10755 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010756 request.traffic_annotation =
10757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710758
danakj1fd259a02016-04-16 03:17:0910759 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610760 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710761
[email protected]270c6412010-03-29 22:02:4710762 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310763 MockWrite(
10764 "GET / HTTP/1.1\r\n"
10765 "Host: www.example.org\r\n"
10766 "Connection: keep-alive\r\n"
10767 "referer: www.foo.com\r\n"
10768 "hEllo: Kitty\r\n"
10769 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710770 };
10771
10772 // Lastly, the server responds with the actual content.
10773 MockRead data_reads[] = {
10774 MockRead("HTTP/1.0 200 OK\r\n"),
10775 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10776 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610777 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710778 };
10779
Ryan Sleevib8d7ea02018-05-07 20:01:0110780 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710781 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710782
[email protected]49639fa2011-12-20 23:22:4110783 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710784
tfarina42834112016-09-22 13:38:2010785 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110786 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710787
10788 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110789 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710790}
10791
bncd16676a2016-07-20 16:23:0110792TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710793 HttpRequestInfo request;
10794 request.method = "GET";
bncce36dca22015-04-21 22:11:2310795 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010796 request.traffic_annotation =
10797 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710798
Lily Houghton8c2f97d2018-01-22 05:06:5910799 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910800 ProxyResolutionService::CreateFixedFromPacResult(
10801 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110802 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710803 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210804
danakj1fd259a02016-04-16 03:17:0910805 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610806 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210807
[email protected]3cd17242009-06-23 02:59:0210808 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10809 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10810
10811 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410812 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10813 MockWrite("GET / HTTP/1.1\r\n"
10814 "Host: www.example.org\r\n"
10815 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210816
10817 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410818 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10819 MockRead("HTTP/1.0 200 OK\r\n"),
10820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10821 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210822
Ryan Sleevib8d7ea02018-05-07 20:01:0110823 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710824 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210825
[email protected]49639fa2011-12-20 23:22:4110826 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0210827
tfarina42834112016-09-22 13:38:2010828 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110829 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0210830
10831 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110832 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210833
bnc691fda62016-08-12 00:43:1610834 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210835 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0210836
tbansal2ecbbc72016-10-06 17:15:4710837 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2010838 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610839 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010840 TestLoadTimingNotReusedWithPac(load_timing_info,
10841 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10842
[email protected]3cd17242009-06-23 02:59:0210843 std::string response_text;
bnc691fda62016-08-12 00:43:1610844 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110845 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210846 EXPECT_EQ("Payload", response_text);
10847}
10848
bncd16676a2016-07-20 16:23:0110849TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710850 HttpRequestInfo request;
10851 request.method = "GET";
bncce36dca22015-04-21 22:11:2310852 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010853 request.traffic_annotation =
10854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710855
Lily Houghton8c2f97d2018-01-22 05:06:5910856 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910857 ProxyResolutionService::CreateFixedFromPacResult(
10858 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110859 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710860 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210861
danakj1fd259a02016-04-16 03:17:0910862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610863 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210864
[email protected]3cd17242009-06-23 02:59:0210865 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
10866 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10867
10868 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310869 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2410870 base::size(write_buffer)),
10871 MockWrite("GET / HTTP/1.1\r\n"
10872 "Host: www.example.org\r\n"
10873 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210874
10875 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410876 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
10877 base::size(read_buffer)),
10878 MockRead("HTTP/1.0 200 OK\r\n"),
10879 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10880 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3510881
Ryan Sleevib8d7ea02018-05-07 20:01:0110882 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710883 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3510884
[email protected]8ddf8322012-02-23 18:08:0610885 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710886 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3510887
[email protected]49639fa2011-12-20 23:22:4110888 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3510889
tfarina42834112016-09-22 13:38:2010890 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110891 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3510892
10893 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110894 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510895
[email protected]029c83b62013-01-24 05:28:2010896 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610897 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010898 TestLoadTimingNotReusedWithPac(load_timing_info,
10899 CONNECT_TIMING_HAS_SSL_TIMES);
10900
bnc691fda62016-08-12 00:43:1610901 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210902 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4710903 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3510904
10905 std::string response_text;
bnc691fda62016-08-12 00:43:1610906 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110907 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510908 EXPECT_EQ("Payload", response_text);
10909}
10910
bncd16676a2016-07-20 16:23:0110911TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2010912 HttpRequestInfo request;
10913 request.method = "GET";
bncce36dca22015-04-21 22:11:2310914 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010915 request.traffic_annotation =
10916 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2010917
Ramin Halavatica8d5252018-03-12 05:33:4910918 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10919 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110920 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710921 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2010922
danakj1fd259a02016-04-16 03:17:0910923 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610924 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2010925
10926 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10927 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10928
10929 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410930 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10931 MockWrite("GET / HTTP/1.1\r\n"
10932 "Host: www.example.org\r\n"
10933 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2010934
10935 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410936 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10937 MockRead("HTTP/1.0 200 OK\r\n"),
10938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10939 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2010940
Ryan Sleevib8d7ea02018-05-07 20:01:0110941 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710942 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2010943
10944 TestCompletionCallback callback;
10945
tfarina42834112016-09-22 13:38:2010946 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110947 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2010948
10949 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110950 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010951
bnc691fda62016-08-12 00:43:1610952 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210953 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2010954
10955 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610956 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010957 TestLoadTimingNotReused(load_timing_info,
10958 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10959
10960 std::string response_text;
bnc691fda62016-08-12 00:43:1610961 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110962 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010963 EXPECT_EQ("Payload", response_text);
10964}
10965
bncd16676a2016-07-20 16:23:0110966TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710967 HttpRequestInfo request;
10968 request.method = "GET";
bncce36dca22015-04-21 22:11:2310969 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010970 request.traffic_annotation =
10971 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710972
Lily Houghton8c2f97d2018-01-22 05:06:5910973 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910974 ProxyResolutionService::CreateFixedFromPacResult(
10975 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110976 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710977 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3510978
danakj1fd259a02016-04-16 03:17:0910979 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610980 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3510981
[email protected]e0c27be2009-07-15 13:09:3510982 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
10983 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3710984 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2310985 0x05, // Version
10986 0x01, // Command (CONNECT)
10987 0x00, // Reserved.
10988 0x03, // Address type (DOMAINNAME).
10989 0x0F, // Length of domain (15)
10990 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
10991 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3710992 };
[email protected]e0c27be2009-07-15 13:09:3510993 const char kSOCKS5OkResponse[] =
10994 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
10995
10996 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410997 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
10998 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
10999 MockWrite("GET / HTTP/1.1\r\n"
11000 "Host: www.example.org\r\n"
11001 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511002
11003 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411004 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11005 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11006 MockRead("HTTP/1.0 200 OK\r\n"),
11007 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11008 MockRead("Payload"),
11009 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511010
Ryan Sleevib8d7ea02018-05-07 20:01:0111011 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711012 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511013
[email protected]49639fa2011-12-20 23:22:4111014 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511015
tfarina42834112016-09-22 13:38:2011016 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111017 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511018
11019 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111020 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511021
bnc691fda62016-08-12 00:43:1611022 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211023 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711024 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511025
[email protected]029c83b62013-01-24 05:28:2011026 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611027 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011028 TestLoadTimingNotReusedWithPac(load_timing_info,
11029 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11030
[email protected]e0c27be2009-07-15 13:09:3511031 std::string response_text;
bnc691fda62016-08-12 00:43:1611032 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111033 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511034 EXPECT_EQ("Payload", response_text);
11035}
11036
bncd16676a2016-07-20 16:23:0111037TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711038 HttpRequestInfo request;
11039 request.method = "GET";
bncce36dca22015-04-21 22:11:2311040 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011041 request.traffic_annotation =
11042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711043
Lily Houghton8c2f97d2018-01-22 05:06:5911044 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911045 ProxyResolutionService::CreateFixedFromPacResult(
11046 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111047 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711048 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511049
danakj1fd259a02016-04-16 03:17:0911050 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611051 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511052
[email protected]e0c27be2009-07-15 13:09:3511053 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11054 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711055 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311056 0x05, // Version
11057 0x01, // Command (CONNECT)
11058 0x00, // Reserved.
11059 0x03, // Address type (DOMAINNAME).
11060 0x0F, // Length of domain (15)
11061 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11062 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711063 };
11064
[email protected]e0c27be2009-07-15 13:09:3511065 const char kSOCKS5OkResponse[] =
11066 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11067
11068 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411069 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311070 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411071 base::size(kSOCKS5OkRequest)),
11072 MockWrite("GET / HTTP/1.1\r\n"
11073 "Host: www.example.org\r\n"
11074 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511075
11076 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411077 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11078 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11079 MockRead("HTTP/1.0 200 OK\r\n"),
11080 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11081 MockRead("Payload"),
11082 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211083
Ryan Sleevib8d7ea02018-05-07 20:01:0111084 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711085 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211086
[email protected]8ddf8322012-02-23 18:08:0611087 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211089
[email protected]49639fa2011-12-20 23:22:4111090 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211091
tfarina42834112016-09-22 13:38:2011092 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111093 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211094
11095 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111096 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211097
bnc691fda62016-08-12 00:43:1611098 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211099 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711100 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211101
[email protected]029c83b62013-01-24 05:28:2011102 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611103 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011104 TestLoadTimingNotReusedWithPac(load_timing_info,
11105 CONNECT_TIMING_HAS_SSL_TIMES);
11106
[email protected]3cd17242009-06-23 02:59:0211107 std::string response_text;
bnc691fda62016-08-12 00:43:1611108 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111109 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211110 EXPECT_EQ("Payload", response_text);
11111}
11112
[email protected]448d4ca52012-03-04 04:12:2311113namespace {
11114
Matt Menkef6edce752019-03-19 17:21:5611115// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611116
Matt Menkef6edce752019-03-19 17:21:5611117struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611118 std::string proxy_server;
11119 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611120 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811121 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611122};
11123
Matt Menkef6edce752019-03-19 17:21:5611124std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711125 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911126 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611127
bnc525e175a2016-06-20 12:36:4011128 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311129 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111130 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211131 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111132 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211133 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711134 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611135
11136 return session;
11137}
11138
Matt Menkef6edce752019-03-19 17:21:5611139int GroupIdTransactionHelper(const std::string& url,
11140 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611141 HttpRequestInfo request;
11142 request.method = "GET";
11143 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011144 request.traffic_annotation =
11145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611146
bnc691fda62016-08-12 00:43:1611147 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711148
[email protected]49639fa2011-12-20 23:22:4111149 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611150
11151 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011152 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611153}
11154
[email protected]448d4ca52012-03-04 04:12:2311155} // namespace
11156
Matt Menkef6edce752019-03-19 17:21:5611157TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11158 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311159 {
Matt Menkef6edce752019-03-19 17:21:5611160 "", // unused
11161 "http://www.example.org/direct",
11162 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11163 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911164 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611165 false,
bncce36dca22015-04-21 22:11:2311166 },
11167 {
Matt Menkef6edce752019-03-19 17:21:5611168 "", // unused
11169 "http://[2001:1418:13:1::25]/direct",
11170 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11171 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911172 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611173 false,
bncce36dca22015-04-21 22:11:2311174 },
[email protected]04e5be32009-06-26 20:00:3111175
bncce36dca22015-04-21 22:11:2311176 // SSL Tests
11177 {
Matt Menkef6edce752019-03-19 17:21:5611178 "", // unused
11179 "https://www.example.org/direct_ssl",
11180 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11181 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911182 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611183 true,
bncce36dca22015-04-21 22:11:2311184 },
11185 {
Matt Menkef6edce752019-03-19 17:21:5611186 "", // unused
11187 "https://[2001:1418:13:1::25]/direct",
11188 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11189 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911190 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611191 true,
bncce36dca22015-04-21 22:11:2311192 },
11193 {
Matt Menkef6edce752019-03-19 17:21:5611194 "", // unused
11195 "https://host.with.alternate/direct",
11196 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11197 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911198 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611199 true,
bncce36dca22015-04-21 22:11:2311200 },
[email protected]2d731a32010-04-29 01:04:0611201 };
[email protected]2ff8b312010-04-26 22:20:5411202
Avi Drissman4365a4782018-12-28 19:26:2411203 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911204 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911205 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11206 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911207 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611208 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611209
mmenkee65e7af2015-10-13 17:16:4211210 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611211 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611212 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911213 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011214 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11215 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811216 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611217
11218 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611219 GroupIdTransactionHelper(tests[i].url, session.get()));
11220 EXPECT_EQ(tests[i].expected_group_id,
11221 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311222 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611223 }
[email protected]2d731a32010-04-29 01:04:0611224}
11225
Matt Menkef6edce752019-03-19 17:21:5611226TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11227 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311228 {
Matt Menke4802de62019-03-08 22:47:5011229 "http_proxy",
11230 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611231 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11232 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911233 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011234 false,
bncce36dca22015-04-21 22:11:2311235 },
[email protected]2d731a32010-04-29 01:04:0611236
bncce36dca22015-04-21 22:11:2311237 // SSL Tests
11238 {
Matt Menke4802de62019-03-08 22:47:5011239 "http_proxy",
11240 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611241 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11242 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911243 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011244 true,
bncce36dca22015-04-21 22:11:2311245 },
[email protected]af3490e2010-10-16 21:02:2911246
bncce36dca22015-04-21 22:11:2311247 {
Matt Menke4802de62019-03-08 22:47:5011248 "http_proxy",
11249 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611250 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11251 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911252 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011253 true,
bncce36dca22015-04-21 22:11:2311254 },
[email protected]2d731a32010-04-29 01:04:0611255 };
11256
Avi Drissman4365a4782018-12-28 19:26:2411257 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911258 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911259 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11260 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911261 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611262 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611263
mmenkee65e7af2015-10-13 17:16:4211264 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611265
Matt Menkee8648fa2019-01-17 16:47:0711266 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11267 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611268 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611269 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911270 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011271 mock_pool_manager->SetSocketPool(proxy_server,
11272 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811273 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611274
11275 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611276 GroupIdTransactionHelper(tests[i].url, session.get()));
11277 EXPECT_EQ(tests[i].expected_group_id,
11278 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611279 }
[email protected]2d731a32010-04-29 01:04:0611280}
11281
Matt Menkef6edce752019-03-19 17:21:5611282TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11283 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311284 {
Matt Menke4802de62019-03-08 22:47:5011285 "socks4://socks_proxy:1080",
11286 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611287 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11288 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911289 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011290 false,
bncce36dca22015-04-21 22:11:2311291 },
11292 {
Matt Menke4802de62019-03-08 22:47:5011293 "socks5://socks_proxy:1080",
11294 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611295 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11296 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911297 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011298 false,
bncce36dca22015-04-21 22:11:2311299 },
[email protected]2d731a32010-04-29 01:04:0611300
bncce36dca22015-04-21 22:11:2311301 // SSL Tests
11302 {
Matt Menke4802de62019-03-08 22:47:5011303 "socks4://socks_proxy:1080",
11304 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611305 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11306 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911307 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011308 true,
bncce36dca22015-04-21 22:11:2311309 },
11310 {
Matt Menke4802de62019-03-08 22:47:5011311 "socks5://socks_proxy:1080",
11312 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611313 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11314 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911315 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011316 true,
bncce36dca22015-04-21 22:11:2311317 },
[email protected]af3490e2010-10-16 21:02:2911318
bncce36dca22015-04-21 22:11:2311319 {
Matt Menke4802de62019-03-08 22:47:5011320 "socks4://socks_proxy:1080",
11321 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611322 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11323 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911324 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011325 true,
bncce36dca22015-04-21 22:11:2311326 },
[email protected]04e5be32009-06-26 20:00:3111327 };
11328
Avi Drissman4365a4782018-12-28 19:26:2411329 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911330 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911331 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11332 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911333 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611334 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211335
mmenkee65e7af2015-10-13 17:16:4211336 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111337
Matt Menkee8648fa2019-01-17 16:47:0711338 ProxyServer proxy_server(
11339 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11340 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611341 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611342 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911343 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011344 mock_pool_manager->SetSocketPool(proxy_server,
11345 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811346 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111347
bnc691fda62016-08-12 00:43:1611348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111349
[email protected]2d731a32010-04-29 01:04:0611350 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611351 GroupIdTransactionHelper(tests[i].url, session.get()));
11352 EXPECT_EQ(tests[i].expected_group_id,
11353 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111354 }
11355}
11356
bncd16676a2016-07-20 16:23:0111357TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711358 HttpRequestInfo request;
11359 request.method = "GET";
bncce36dca22015-04-21 22:11:2311360 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011361 request.traffic_annotation =
11362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711363
Ramin Halavatica8d5252018-03-12 05:33:4911364 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11365 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211366
[email protected]69719062010-01-05 20:09:2111367 // This simulates failure resolving all hostnames; that means we will fail
11368 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711369 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211370
danakj1fd259a02016-04-16 03:17:0911371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611372 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511373
[email protected]49639fa2011-12-20 23:22:4111374 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511375
tfarina42834112016-09-22 13:38:2011376 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111377 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511378
[email protected]9172a982009-06-06 00:30:2511379 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111380 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511381}
11382
[email protected]0877e3d2009-10-17 22:29:5711383// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111384TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711385 HttpRequestInfo request;
11386 request.method = "GET";
11387 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011388 request.traffic_annotation =
11389 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711390
11391 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611392 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711393 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111394 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711395 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911396 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711397
[email protected]49639fa2011-12-20 23:22:4111398 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711399
bnc691fda62016-08-12 00:43:1611400 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711401
tfarina42834112016-09-22 13:38:2011402 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711404
11405 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111406 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911407
11408 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611409 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911410 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711411}
11412
zmo9528c9f42015-08-04 22:12:0811413// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111414TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711415 HttpRequestInfo request;
11416 request.method = "GET";
11417 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011418 request.traffic_annotation =
11419 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711420
11421 MockRead data_reads[] = {
11422 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611423 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711424 };
11425
Ryan Sleevib8d7ea02018-05-07 20:01:0111426 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711427 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711429
[email protected]49639fa2011-12-20 23:22:4111430 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711431
bnc691fda62016-08-12 00:43:1611432 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711433
tfarina42834112016-09-22 13:38:2011434 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111435 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711436
11437 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111438 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811439
bnc691fda62016-08-12 00:43:1611440 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211441 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811442
wezca1070932016-05-26 20:30:5211443 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811444 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11445
11446 std::string response_data;
bnc691fda62016-08-12 00:43:1611447 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111448 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811449 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911450
11451 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611452 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911453 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711454}
11455
11456// Make sure that a dropped connection while draining the body for auth
11457// restart does the right thing.
bncd16676a2016-07-20 16:23:0111458TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711459 HttpRequestInfo request;
11460 request.method = "GET";
bncce36dca22015-04-21 22:11:2311461 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011462 request.traffic_annotation =
11463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711464
11465 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311466 MockWrite(
11467 "GET / HTTP/1.1\r\n"
11468 "Host: www.example.org\r\n"
11469 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711470 };
11471
11472 MockRead data_reads1[] = {
11473 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11474 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11475 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11476 MockRead("Content-Length: 14\r\n\r\n"),
11477 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611478 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711479 };
11480
Ryan Sleevib8d7ea02018-05-07 20:01:0111481 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711482 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711483
bnc691fda62016-08-12 00:43:1611484 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711485 // be issuing -- the final header line contains the credentials.
11486 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311487 MockWrite(
11488 "GET / HTTP/1.1\r\n"
11489 "Host: www.example.org\r\n"
11490 "Connection: keep-alive\r\n"
11491 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711492 };
11493
11494 // Lastly, the server responds with the actual content.
11495 MockRead data_reads2[] = {
11496 MockRead("HTTP/1.1 200 OK\r\n"),
11497 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11498 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611499 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711500 };
11501
Ryan Sleevib8d7ea02018-05-07 20:01:0111502 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711503 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911504 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711505
[email protected]49639fa2011-12-20 23:22:4111506 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711507
bnc691fda62016-08-12 00:43:1611508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011509
tfarina42834112016-09-22 13:38:2011510 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111511 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711512
11513 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111514 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711515
bnc691fda62016-08-12 00:43:1611516 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211517 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811518 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711519
[email protected]49639fa2011-12-20 23:22:4111520 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711521
bnc691fda62016-08-12 00:43:1611522 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711524
11525 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111526 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711527
bnc691fda62016-08-12 00:43:1611528 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211529 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811530 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711531 EXPECT_EQ(100, response->headers->GetContentLength());
11532}
11533
11534// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111535TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911536 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11537 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711538
11539 HttpRequestInfo request;
11540 request.method = "GET";
bncce36dca22015-04-21 22:11:2311541 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011542 request.traffic_annotation =
11543 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711544
11545 MockRead proxy_reads[] = {
11546 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611547 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711548 };
11549
Ryan Sleevib8d7ea02018-05-07 20:01:0111550 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611551 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711552
[email protected]bb88e1d32013-05-03 23:11:0711553 session_deps_.socket_factory->AddSocketDataProvider(&data);
11554 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711555
[email protected]49639fa2011-12-20 23:22:4111556 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711557
[email protected]bb88e1d32013-05-03 23:11:0711558 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711559
danakj1fd259a02016-04-16 03:17:0911560 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611561 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711562
tfarina42834112016-09-22 13:38:2011563 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111564 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711565
11566 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111567 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711568}
11569
bncd16676a2016-07-20 16:23:0111570TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611571 HttpRequestInfo request;
11572 request.method = "GET";
bncce36dca22015-04-21 22:11:2311573 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011574 request.traffic_annotation =
11575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611576
danakj1fd259a02016-04-16 03:17:0911577 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611578 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711579
[email protected]e22e1362009-11-23 21:31:1211580 MockRead data_reads[] = {
11581 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611582 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211583 };
[email protected]9492e4a2010-02-24 00:58:4611584
Ryan Sleevib8d7ea02018-05-07 20:01:0111585 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711586 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611587
[email protected]49639fa2011-12-20 23:22:4111588 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611589
tfarina42834112016-09-22 13:38:2011590 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111591 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611592
robpercival214763f2016-07-01 23:27:0111593 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611594
bnc691fda62016-08-12 00:43:1611595 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211596 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611597
wezca1070932016-05-26 20:30:5211598 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611599 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11600
11601 std::string response_data;
bnc691fda62016-08-12 00:43:1611602 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111603 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211604}
11605
bncd16676a2016-07-20 16:23:0111606TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511607 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211608 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411609 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111610 UploadFileElementReader::ScopedOverridingContentLengthForTests
11611 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311612
danakj1fd259a02016-04-16 03:17:0911613 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911614 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411615 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711616 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211617 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711618
11619 HttpRequestInfo request;
11620 request.method = "POST";
bncce36dca22015-04-21 22:11:2311621 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711622 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011623 request.traffic_annotation =
11624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711625
danakj1fd259a02016-04-16 03:17:0911626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611627 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311628
11629 MockRead data_reads[] = {
11630 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11631 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611632 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311633 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111634 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711635 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311636
[email protected]49639fa2011-12-20 23:22:4111637 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311638
tfarina42834112016-09-22 13:38:2011639 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311641
11642 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111643 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311644
bnc691fda62016-08-12 00:43:1611645 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211646 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311647
maksim.sisove869bf52016-06-23 17:11:5211648 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311649
[email protected]dd3aa792013-07-16 19:10:2311650 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311651}
11652
bncd16676a2016-07-20 16:23:0111653TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511654 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211655 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611656 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811657 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11658 base::WriteFile(temp_file, temp_file_content.c_str(),
11659 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111660 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611661
danakj1fd259a02016-04-16 03:17:0911662 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911663 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411664 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711665 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211666 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711667
11668 HttpRequestInfo request;
11669 request.method = "POST";
bncce36dca22015-04-21 22:11:2311670 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711671 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011672 request.traffic_annotation =
11673 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711674
[email protected]999dd8c2013-11-12 06:45:5411675 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911676 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611677 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611678
Ryan Sleevib8d7ea02018-05-07 20:01:0111679 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711680 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611681
[email protected]49639fa2011-12-20 23:22:4111682 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611683
tfarina42834112016-09-22 13:38:2011684 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111685 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611686
11687 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111688 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611689
[email protected]dd3aa792013-07-16 19:10:2311690 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611691}
11692
bncd16676a2016-07-20 16:23:0111693TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311694 class FakeUploadElementReader : public UploadElementReader {
11695 public:
Chris Watkins7a41d3552017-12-01 02:13:2711696 FakeUploadElementReader() = default;
11697 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311698
Matt Menkecc1d3a902018-02-05 18:27:3311699 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311700
11701 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311702 int Init(CompletionOnceCallback callback) override {
11703 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311704 return ERR_IO_PENDING;
11705 }
avibf0746c2015-12-09 19:53:1411706 uint64_t GetContentLength() const override { return 0; }
11707 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011708 int Read(IOBuffer* buf,
11709 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311710 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311711 return ERR_FAILED;
11712 }
11713
11714 private:
Matt Menkecc1d3a902018-02-05 18:27:3311715 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311716 };
11717
11718 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911719 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11720 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211721 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311722
11723 HttpRequestInfo request;
11724 request.method = "POST";
bncce36dca22015-04-21 22:11:2311725 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311726 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011727 request.traffic_annotation =
11728 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311729
danakj1fd259a02016-04-16 03:17:0911730 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811731 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911732 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311733
11734 StaticSocketDataProvider data;
11735 session_deps_.socket_factory->AddSocketDataProvider(&data);
11736
11737 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011738 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111739 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511740 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311741
11742 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311743 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11744 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311745
11746 // Return Init()'s result after the transaction gets destroyed.
11747 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311748 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311749}
11750
[email protected]aeefc9e82010-02-19 16:18:2711751// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111752TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711753 HttpRequestInfo request;
11754 request.method = "GET";
bncce36dca22015-04-21 22:11:2311755 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011756 request.traffic_annotation =
11757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711758
11759 // First transaction will request a resource and receive a Basic challenge
11760 // with realm="first_realm".
11761 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311762 MockWrite(
11763 "GET / HTTP/1.1\r\n"
11764 "Host: www.example.org\r\n"
11765 "Connection: keep-alive\r\n"
11766 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711767 };
11768 MockRead data_reads1[] = {
11769 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11770 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11771 "\r\n"),
11772 };
11773
bnc691fda62016-08-12 00:43:1611774 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711775 // for first_realm. The server will reject and provide a challenge with
11776 // second_realm.
11777 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311778 MockWrite(
11779 "GET / HTTP/1.1\r\n"
11780 "Host: www.example.org\r\n"
11781 "Connection: keep-alive\r\n"
11782 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11783 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711784 };
11785 MockRead data_reads2[] = {
11786 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11787 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11788 "\r\n"),
11789 };
11790
11791 // This again fails, and goes back to first_realm. Make sure that the
11792 // entry is removed from cache.
11793 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311794 MockWrite(
11795 "GET / HTTP/1.1\r\n"
11796 "Host: www.example.org\r\n"
11797 "Connection: keep-alive\r\n"
11798 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11799 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711800 };
11801 MockRead data_reads3[] = {
11802 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11803 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11804 "\r\n"),
11805 };
11806
11807 // Try one last time (with the correct password) and get the resource.
11808 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2311809 MockWrite(
11810 "GET / HTTP/1.1\r\n"
11811 "Host: www.example.org\r\n"
11812 "Connection: keep-alive\r\n"
11813 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
11814 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711815 };
11816 MockRead data_reads4[] = {
11817 MockRead("HTTP/1.1 200 OK\r\n"
11818 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5011819 "Content-Length: 5\r\n"
11820 "\r\n"
11821 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2711822 };
11823
Ryan Sleevib8d7ea02018-05-07 20:01:0111824 StaticSocketDataProvider data1(data_reads1, data_writes1);
11825 StaticSocketDataProvider data2(data_reads2, data_writes2);
11826 StaticSocketDataProvider data3(data_reads3, data_writes3);
11827 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0711828 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11829 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11830 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11831 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2711832
[email protected]49639fa2011-12-20 23:22:4111833 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2711834
danakj1fd259a02016-04-16 03:17:0911835 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611836 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011837
[email protected]aeefc9e82010-02-19 16:18:2711838 // Issue the first request with Authorize headers. There should be a
11839 // password prompt for first_realm waiting to be filled in after the
11840 // transaction completes.
tfarina42834112016-09-22 13:38:2011841 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111842 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711843 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111844 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611845 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211846 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811847 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211848 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411849 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311850 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411851 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911852 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711853
11854 // Issue the second request with an incorrect password. There should be a
11855 // password prompt for second_realm waiting to be filled in after the
11856 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4111857 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1611858 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
11859 callback2.callback());
robpercival214763f2016-07-01 23:27:0111860 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711861 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111862 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611863 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211864 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811865 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211866 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411867 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311868 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411869 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911870 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711871
11872 // Issue the third request with another incorrect password. There should be
11873 // a password prompt for first_realm waiting to be filled in. If the password
11874 // prompt is not present, it indicates that the HttpAuthCacheEntry for
11875 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4111876 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1611877 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
11878 callback3.callback());
robpercival214763f2016-07-01 23:27:0111879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711880 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0111881 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611882 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211883 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811884 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211885 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411886 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311887 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411888 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911889 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711890
11891 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4111892 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1611893 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
11894 callback4.callback());
robpercival214763f2016-07-01 23:27:0111895 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711896 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0111897 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611898 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211899 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811900 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2711901}
11902
Bence Béky230ac612017-08-30 19:17:0811903// Regression test for https://crbug.com/754395.
11904TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
11905 MockRead data_reads[] = {
11906 MockRead("HTTP/1.1 200 OK\r\n"),
11907 MockRead(kAlternativeServiceHttpHeader),
11908 MockRead("\r\n"),
11909 MockRead("hello world"),
11910 MockRead(SYNCHRONOUS, OK),
11911 };
11912
11913 HttpRequestInfo request;
11914 request.method = "GET";
11915 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011916 request.traffic_annotation =
11917 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0811918
Ryan Sleevib8d7ea02018-05-07 20:01:0111919 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0811920 session_deps_.socket_factory->AddSocketDataProvider(&data);
11921
11922 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911923 ssl.ssl_info.cert =
11924 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11925 ASSERT_TRUE(ssl.ssl_info.cert);
11926 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0811927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11928
11929 TestCompletionCallback callback;
11930
11931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11932 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11933
11934 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11935 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11936
11937 url::SchemeHostPort test_server(request.url);
11938 HttpServerProperties* http_server_properties =
11939 session->http_server_properties();
11940 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4911941 http_server_properties
11942 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
11943 .empty());
Bence Béky230ac612017-08-30 19:17:0811944
11945 EXPECT_THAT(callback.WaitForResult(), IsOk());
11946
11947 const HttpResponseInfo* response = trans.GetResponseInfo();
11948 ASSERT_TRUE(response);
11949 ASSERT_TRUE(response->headers);
11950 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11951 EXPECT_FALSE(response->was_fetched_via_spdy);
11952 EXPECT_FALSE(response->was_alpn_negotiated);
11953
11954 std::string response_data;
11955 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
11956 EXPECT_EQ("hello world", response_data);
11957
11958 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4911959 http_server_properties
11960 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
11961 .empty());
Bence Béky230ac612017-08-30 19:17:0811962}
11963
bncd16676a2016-07-20 16:23:0111964TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5211965 MockRead data_reads[] = {
11966 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311967 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211968 MockRead("\r\n"),
11969 MockRead("hello world"),
11970 MockRead(SYNCHRONOUS, OK),
11971 };
11972
11973 HttpRequestInfo request;
11974 request.method = "GET";
bncb26024382016-06-29 02:39:4511975 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011976 request.traffic_annotation =
11977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5211978
Ryan Sleevib8d7ea02018-05-07 20:01:0111979 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5211980 session_deps_.socket_factory->AddSocketDataProvider(&data);
11981
bncb26024382016-06-29 02:39:4511982 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911983 ssl.ssl_info.cert =
11984 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11985 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4511986 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11987
bncc958faa2015-07-31 18:14:5211988 TestCompletionCallback callback;
11989
danakj1fd259a02016-04-16 03:17:0911990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611991 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5211992
tfarina42834112016-09-22 13:38:2011993 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111994 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5211995
bncb26024382016-06-29 02:39:4511996 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4011997 HttpServerProperties* http_server_properties =
11998 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3411999 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912000 http_server_properties
12001 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12002 .empty());
bncc958faa2015-07-31 18:14:5212003
robpercival214763f2016-07-01 23:27:0112004 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212005
bnc691fda62016-08-12 00:43:1612006 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212007 ASSERT_TRUE(response);
12008 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212009 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12010 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212011 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212012
12013 std::string response_data;
bnc691fda62016-08-12 00:43:1612014 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212015 EXPECT_EQ("hello world", response_data);
12016
zhongyic4de03032017-05-19 04:07:3412017 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912018 http_server_properties->GetAlternativeServiceInfos(test_server,
12019 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412020 ASSERT_EQ(1u, alternative_service_info_vector.size());
12021 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12022 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412023 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212024}
12025
Matt Menke3233d8f22019-08-20 21:01:4912026TEST_F(HttpNetworkTransactionTest,
12027 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12028 base::test::ScopedFeatureList feature_list;
12029 feature_list.InitWithFeatures(
12030 // enabled_features
12031 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12032 // Need to partition connections by NetworkIsolationKey for
12033 // SpdySessionKeys to include NetworkIsolationKeys.
12034 features::kPartitionConnectionsByNetworkIsolationKey},
12035 // disabled_features
12036 {});
12037 // Since HttpServerProperties caches the feature value, have to create a new
12038 // one.
12039 session_deps_.http_server_properties =
12040 std::make_unique<HttpServerProperties>();
12041
12042 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12043 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12044 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12045 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12046
12047 MockRead data_reads[] = {
12048 MockRead("HTTP/1.1 200 OK\r\n"),
12049 MockRead(kAlternativeServiceHttpHeader),
12050 MockRead("\r\n"),
12051 MockRead("hello world"),
12052 MockRead(SYNCHRONOUS, OK),
12053 };
12054
12055 HttpRequestInfo request;
12056 request.method = "GET";
12057 request.url = GURL("https://www.example.org/");
12058 request.traffic_annotation =
12059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12060 request.network_isolation_key = kNetworkIsolationKey1;
12061
12062 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12063 session_deps_.socket_factory->AddSocketDataProvider(&data);
12064
12065 SSLSocketDataProvider ssl(ASYNC, OK);
12066 ssl.ssl_info.cert =
12067 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12068 ASSERT_TRUE(ssl.ssl_info.cert);
12069 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12070
12071 TestCompletionCallback callback;
12072
12073 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12074 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12075
12076 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12078
12079 url::SchemeHostPort test_server(request.url);
12080 HttpServerProperties* http_server_properties =
12081 session->http_server_properties();
12082 EXPECT_TRUE(
12083 http_server_properties
12084 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12085 .empty());
12086
12087 EXPECT_THAT(callback.WaitForResult(), IsOk());
12088
12089 const HttpResponseInfo* response = trans.GetResponseInfo();
12090 ASSERT_TRUE(response);
12091 ASSERT_TRUE(response->headers);
12092 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12093 EXPECT_FALSE(response->was_fetched_via_spdy);
12094 EXPECT_FALSE(response->was_alpn_negotiated);
12095
12096 std::string response_data;
12097 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12098 EXPECT_EQ("hello world", response_data);
12099
12100 AlternativeServiceInfoVector alternative_service_info_vector =
12101 http_server_properties->GetAlternativeServiceInfos(test_server,
12102 kNetworkIsolationKey1);
12103 ASSERT_EQ(1u, alternative_service_info_vector.size());
12104 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12105 EXPECT_EQ(alternative_service,
12106 alternative_service_info_vector[0].alternative_service());
12107
12108 // Make sure the alternative service information is only associated with
12109 // kNetworkIsolationKey1.
12110 EXPECT_TRUE(
12111 http_server_properties
12112 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12113 .empty());
12114 EXPECT_TRUE(
12115 http_server_properties
12116 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
12117 .empty());
12118}
12119
bnce3dd56f2016-06-01 10:37:1112120// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112121TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112122 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112123 MockRead data_reads[] = {
12124 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312125 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112126 MockRead("\r\n"),
12127 MockRead("hello world"),
12128 MockRead(SYNCHRONOUS, OK),
12129 };
12130
12131 HttpRequestInfo request;
12132 request.method = "GET";
12133 request.url = GURL("http://www.example.org/");
12134 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012135 request.traffic_annotation =
12136 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112137
Ryan Sleevib8d7ea02018-05-07 20:01:0112138 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112139 session_deps_.socket_factory->AddSocketDataProvider(&data);
12140
12141 TestCompletionCallback callback;
12142
12143 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612144 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112145
12146 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012147 HttpServerProperties* http_server_properties =
12148 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412149 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912150 http_server_properties
12151 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12152 .empty());
bnce3dd56f2016-06-01 10:37:1112153
tfarina42834112016-09-22 13:38:2012154 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112155 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12156 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112157
bnc691fda62016-08-12 00:43:1612158 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112159 ASSERT_TRUE(response);
12160 ASSERT_TRUE(response->headers);
12161 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12162 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212163 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112164
12165 std::string response_data;
bnc691fda62016-08-12 00:43:1612166 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112167 EXPECT_EQ("hello world", response_data);
12168
zhongyic4de03032017-05-19 04:07:3412169 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912170 http_server_properties
12171 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12172 .empty());
bnce3dd56f2016-06-01 10:37:1112173}
12174
bnca86731e2017-04-17 12:31:2812175// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512176// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112177TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512178 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812179 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512180
bnc8bef8da22016-05-30 01:28:2512181 HttpRequestInfo request;
12182 request.method = "GET";
bncb26024382016-06-29 02:39:4512183 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512184 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012185 request.traffic_annotation =
12186 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512187
12188 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12189 StaticSocketDataProvider first_data;
12190 first_data.set_connect_data(mock_connect);
12191 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512192 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612193 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512195
12196 MockRead data_reads[] = {
12197 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12198 MockRead(ASYNC, OK),
12199 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112200 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512201 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12202
12203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12204
bnc525e175a2016-06-20 12:36:4012205 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512206 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112207 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12208 444);
bnc8bef8da22016-05-30 01:28:2512209 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112210 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712211 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12212 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2512213
bnc691fda62016-08-12 00:43:1612214 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512215 TestCompletionCallback callback;
12216
tfarina42834112016-09-22 13:38:2012217 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512218 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112219 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512220}
12221
bnce3dd56f2016-06-01 10:37:1112222// Regression test for https://crbug.com/615497:
12223// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112224TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112225 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112226 HttpRequestInfo request;
12227 request.method = "GET";
12228 request.url = GURL("http://www.example.org/");
12229 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012230 request.traffic_annotation =
12231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112232
12233 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12234 StaticSocketDataProvider first_data;
12235 first_data.set_connect_data(mock_connect);
12236 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12237
12238 MockRead data_reads[] = {
12239 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12240 MockRead(ASYNC, OK),
12241 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112242 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112243 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12244
12245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12246
bnc525e175a2016-06-20 12:36:4012247 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112248 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112249 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112250 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112251 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712252 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12253 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1112254
bnc691fda62016-08-12 00:43:1612255 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112256 TestCompletionCallback callback;
12257
tfarina42834112016-09-22 13:38:2012258 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112259 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112260 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112261}
12262
bncd16676a2016-07-20 16:23:0112263TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812264 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912265 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012266 HttpServerProperties* http_server_properties =
12267 session->http_server_properties();
bncb26024382016-06-29 02:39:4512268 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112269 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812270 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112271 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712272 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212273 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4912274 EXPECT_EQ(1u,
12275 http_server_properties
12276 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12277 .size());
bnc4f575852015-10-14 18:35:0812278
12279 // Send a clear header.
12280 MockRead data_reads[] = {
12281 MockRead("HTTP/1.1 200 OK\r\n"),
12282 MockRead("Alt-Svc: clear\r\n"),
12283 MockRead("\r\n"),
12284 MockRead("hello world"),
12285 MockRead(SYNCHRONOUS, OK),
12286 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112287 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812288 session_deps_.socket_factory->AddSocketDataProvider(&data);
12289
bncb26024382016-06-29 02:39:4512290 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912291 ssl.ssl_info.cert =
12292 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12293 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12295
bnc4f575852015-10-14 18:35:0812296 HttpRequestInfo request;
12297 request.method = "GET";
bncb26024382016-06-29 02:39:4512298 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012299 request.traffic_annotation =
12300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812301
12302 TestCompletionCallback callback;
12303
bnc691fda62016-08-12 00:43:1612304 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812305
tfarina42834112016-09-22 13:38:2012306 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112307 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812308
bnc691fda62016-08-12 00:43:1612309 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212310 ASSERT_TRUE(response);
12311 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812312 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12313 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212314 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812315
12316 std::string response_data;
bnc691fda62016-08-12 00:43:1612317 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812318 EXPECT_EQ("hello world", response_data);
12319
zhongyic4de03032017-05-19 04:07:3412320 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912321 http_server_properties
12322 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12323 .empty());
bnc4f575852015-10-14 18:35:0812324}
12325
bncd16676a2016-07-20 16:23:0112326TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212327 MockRead data_reads[] = {
12328 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312329 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12330 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212331 MockRead("hello world"),
12332 MockRead(SYNCHRONOUS, OK),
12333 };
12334
12335 HttpRequestInfo request;
12336 request.method = "GET";
bncb26024382016-06-29 02:39:4512337 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012338 request.traffic_annotation =
12339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212340
Ryan Sleevib8d7ea02018-05-07 20:01:0112341 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212342 session_deps_.socket_factory->AddSocketDataProvider(&data);
12343
bncb26024382016-06-29 02:39:4512344 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912345 ssl.ssl_info.cert =
12346 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12347 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12349
bncc958faa2015-07-31 18:14:5212350 TestCompletionCallback callback;
12351
danakj1fd259a02016-04-16 03:17:0912352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612353 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212354
tfarina42834112016-09-22 13:38:2012355 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112356 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212357
bncb26024382016-06-29 02:39:4512358 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012359 HttpServerProperties* http_server_properties =
12360 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412361 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912362 http_server_properties
12363 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12364 .empty());
bncc958faa2015-07-31 18:14:5212365
robpercival214763f2016-07-01 23:27:0112366 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212367
bnc691fda62016-08-12 00:43:1612368 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212369 ASSERT_TRUE(response);
12370 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212371 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12372 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212373 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212374
12375 std::string response_data;
bnc691fda62016-08-12 00:43:1612376 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212377 EXPECT_EQ("hello world", response_data);
12378
zhongyic4de03032017-05-19 04:07:3412379 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912380 http_server_properties->GetAlternativeServiceInfos(test_server,
12381 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412382 ASSERT_EQ(2u, alternative_service_info_vector.size());
12383
12384 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12385 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412386 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412387 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12388 1234);
12389 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412390 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212391}
12392
bncd16676a2016-07-20 16:23:0112393TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612394 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212395 HostPortPair alternative("alternative.example.org", 443);
12396 std::string origin_url = "https://origin.example.org:443";
12397 std::string alternative_url = "https://alternative.example.org:443";
12398
12399 // Negotiate HTTP/1.1 with alternative.example.org.
12400 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612401 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12403
12404 // HTTP/1.1 data for request.
12405 MockWrite http_writes[] = {
12406 MockWrite("GET / HTTP/1.1\r\n"
12407 "Host: alternative.example.org\r\n"
12408 "Connection: keep-alive\r\n\r\n"),
12409 };
12410
12411 MockRead http_reads[] = {
12412 MockRead("HTTP/1.1 200 OK\r\n"
12413 "Content-Type: text/html; charset=iso-8859-1\r\n"
12414 "Content-Length: 40\r\n\r\n"
12415 "first HTTP/1.1 response from alternative"),
12416 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112417 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212418 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12419
12420 StaticSocketDataProvider data_refused;
12421 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12422 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12423
zhongyi3d4a55e72016-04-22 20:36:4612424 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912425 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012426 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212427 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112428 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212429 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112430 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712431 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212432 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0212433 // Mark the QUIC alternative service as broken.
12434 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
12435
zhongyi48704c182015-12-07 07:52:0212436 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612437 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212438 request.method = "GET";
12439 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012440 request.traffic_annotation =
12441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12442
zhongyi48704c182015-12-07 07:52:0212443 TestCompletionCallback callback;
12444 NetErrorDetails details;
12445 EXPECT_FALSE(details.quic_broken);
12446
tfarina42834112016-09-22 13:38:2012447 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612448 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212449 EXPECT_TRUE(details.quic_broken);
12450}
12451
bncd16676a2016-07-20 16:23:0112452TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612453 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212454 HostPortPair alternative1("alternative1.example.org", 443);
12455 HostPortPair alternative2("alternative2.example.org", 443);
12456 std::string origin_url = "https://origin.example.org:443";
12457 std::string alternative_url1 = "https://alternative1.example.org:443";
12458 std::string alternative_url2 = "https://alternative2.example.org:443";
12459
12460 // Negotiate HTTP/1.1 with alternative1.example.org.
12461 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612462 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12464
12465 // HTTP/1.1 data for request.
12466 MockWrite http_writes[] = {
12467 MockWrite("GET / HTTP/1.1\r\n"
12468 "Host: alternative1.example.org\r\n"
12469 "Connection: keep-alive\r\n\r\n"),
12470 };
12471
12472 MockRead http_reads[] = {
12473 MockRead("HTTP/1.1 200 OK\r\n"
12474 "Content-Type: text/html; charset=iso-8859-1\r\n"
12475 "Content-Length: 40\r\n\r\n"
12476 "first HTTP/1.1 response from alternative1"),
12477 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112478 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212479 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12480
12481 StaticSocketDataProvider data_refused;
12482 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12483 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12484
danakj1fd259a02016-04-16 03:17:0912485 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012486 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212487 session->http_server_properties();
12488
zhongyi3d4a55e72016-04-22 20:36:4612489 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212490 AlternativeServiceInfoVector alternative_service_info_vector;
12491 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12492
bnc3472afd2016-11-17 15:27:2112493 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112494 alternative_service_info_vector.push_back(
12495 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12496 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4212497 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2112498 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112499 alternative_service_info_vector.push_back(
12500 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12501 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4212502 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0212503
12504 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4912505 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212506
12507 // Mark one of the QUIC alternative service as broken.
12508 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
Matt Menke3233d8f22019-08-20 21:01:4912509 EXPECT_EQ(2u, http_server_properties
12510 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
12511 .size());
zhongyi48704c182015-12-07 07:52:0212512
zhongyi48704c182015-12-07 07:52:0212513 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612514 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212515 request.method = "GET";
12516 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012517 request.traffic_annotation =
12518 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12519
zhongyi48704c182015-12-07 07:52:0212520 TestCompletionCallback callback;
12521 NetErrorDetails details;
12522 EXPECT_FALSE(details.quic_broken);
12523
tfarina42834112016-09-22 13:38:2012524 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612525 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212526 EXPECT_FALSE(details.quic_broken);
12527}
12528
bncd16676a2016-07-20 16:23:0112529TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212530 HttpRequestInfo request;
12531 request.method = "GET";
bncb26024382016-06-29 02:39:4512532 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012533 request.traffic_annotation =
12534 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212535
[email protected]d973e99a2012-02-17 21:02:3612536 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212537 StaticSocketDataProvider first_data;
12538 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712539 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512540 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612541 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512542 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212543
12544 MockRead data_reads[] = {
12545 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12546 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612547 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212548 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112549 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712550 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212551
danakj1fd259a02016-04-16 03:17:0912552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212553
bnc525e175a2016-06-20 12:36:4012554 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312555 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612556 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112557 // Port must be < 1024, or the header will be ignored (since initial port was
12558 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112559 // Port is ignored by MockConnect anyway.
12560 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12561 666);
bnc7dc7e1b42015-07-28 14:43:1212562 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112563 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712564 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212565
bnc691fda62016-08-12 00:43:1612566 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112567 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212568
tfarina42834112016-09-22 13:38:2012569 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112570 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12571 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212572
bnc691fda62016-08-12 00:43:1612573 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212574 ASSERT_TRUE(response);
12575 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212576 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12577
12578 std::string response_data;
bnc691fda62016-08-12 00:43:1612579 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212580 EXPECT_EQ("hello world", response_data);
12581
zhongyic4de03032017-05-19 04:07:3412582 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912583 http_server_properties->GetAlternativeServiceInfos(server,
12584 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412585 ASSERT_EQ(1u, alternative_service_info_vector.size());
12586 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412587 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412588 EXPECT_TRUE(
12589 http_server_properties->IsAlternativeServiceBroken(alternative_service));
[email protected]564b4912010-03-09 16:30:4212590}
12591
bnc55ff9da2015-08-19 18:42:3512592// Ensure that we are not allowed to redirect traffic via an alternate protocol
12593// to an unrestricted (port >= 1024) when the original traffic was on a
12594// restricted port (port < 1024). Ensure that we can redirect in all other
12595// cases.
bncd16676a2016-07-20 16:23:0112596TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112597 HttpRequestInfo restricted_port_request;
12598 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512599 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112600 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012601 restricted_port_request.traffic_annotation =
12602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112603
[email protected]d973e99a2012-02-17 21:02:3612604 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112605 StaticSocketDataProvider first_data;
12606 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712607 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112608
12609 MockRead data_reads[] = {
12610 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12611 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612612 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112613 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112614 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712615 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512616 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612617 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512618 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112619
danakj1fd259a02016-04-16 03:17:0912620 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112621
bnc525e175a2016-06-20 12:36:4012622 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312623 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112624 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112625 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12626 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212627 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112628 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712629 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12630 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112631
bnc691fda62016-08-12 00:43:1612632 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112633 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112634
tfarina42834112016-09-22 13:38:2012635 int rv = trans.Start(&restricted_port_request, callback.callback(),
12636 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112638 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112639 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912640}
[email protected]3912662a32011-10-04 00:51:1112641
bnc55ff9da2015-08-19 18:42:3512642// Ensure that we are allowed to redirect traffic via an alternate protocol to
12643// an unrestricted (port >= 1024) when the original traffic was on a restricted
12644// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112645TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712646 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912647
12648 HttpRequestInfo restricted_port_request;
12649 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512650 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912651 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012652 restricted_port_request.traffic_annotation =
12653 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912654
12655 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12656 StaticSocketDataProvider first_data;
12657 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712658 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912659
12660 MockRead data_reads[] = {
12661 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12662 MockRead("hello world"),
12663 MockRead(ASYNC, OK),
12664 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112665 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712666 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512667 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612668 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912670
danakj1fd259a02016-04-16 03:17:0912671 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912672
bnc525e175a2016-06-20 12:36:4012673 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912674 session->http_server_properties();
12675 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112676 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12677 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212678 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112679 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712680 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12681 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1912682
bnc691fda62016-08-12 00:43:1612683 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912684 TestCompletionCallback callback;
12685
tfarina42834112016-09-22 13:38:2012686 EXPECT_EQ(ERR_IO_PENDING,
12687 trans.Start(&restricted_port_request, callback.callback(),
12688 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912689 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112690 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112691}
12692
bnc55ff9da2015-08-19 18:42:3512693// Ensure that we are not allowed to redirect traffic via an alternate protocol
12694// to an unrestricted (port >= 1024) when the original traffic was on a
12695// restricted port (port < 1024). Ensure that we can redirect in all other
12696// cases.
bncd16676a2016-07-20 16:23:0112697TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112698 HttpRequestInfo restricted_port_request;
12699 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512700 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112701 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012702 restricted_port_request.traffic_annotation =
12703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112704
[email protected]d973e99a2012-02-17 21:02:3612705 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112706 StaticSocketDataProvider first_data;
12707 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712708 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112709
12710 MockRead data_reads[] = {
12711 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12712 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612713 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112714 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112715 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712716 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112717
bncb26024382016-06-29 02:39:4512718 SSLSocketDataProvider ssl(ASYNC, OK);
12719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12720
danakj1fd259a02016-04-16 03:17:0912721 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112722
bnc525e175a2016-06-20 12:36:4012723 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312724 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112725 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112726 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12727 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212728 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112729 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712730 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12731 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112732
bnc691fda62016-08-12 00:43:1612733 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112734 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112735
tfarina42834112016-09-22 13:38:2012736 int rv = trans.Start(&restricted_port_request, callback.callback(),
12737 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112739 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112740 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112741}
12742
bnc55ff9da2015-08-19 18:42:3512743// Ensure that we are not allowed to redirect traffic via an alternate protocol
12744// to an unrestricted (port >= 1024) when the original traffic was on a
12745// restricted port (port < 1024). Ensure that we can redirect in all other
12746// cases.
bncd16676a2016-07-20 16:23:0112747TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112748 HttpRequestInfo unrestricted_port_request;
12749 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512750 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112751 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012752 unrestricted_port_request.traffic_annotation =
12753 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112754
[email protected]d973e99a2012-02-17 21:02:3612755 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112756 StaticSocketDataProvider first_data;
12757 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712758 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112759
12760 MockRead data_reads[] = {
12761 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12762 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612763 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112764 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112765 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712766 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512767 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612768 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512769 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112770
danakj1fd259a02016-04-16 03:17:0912771 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112772
bnc525e175a2016-06-20 12:36:4012773 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312774 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112775 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112776 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12777 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212778 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112779 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712780 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
12781 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112782
bnc691fda62016-08-12 00:43:1612783 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112784 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112785
bnc691fda62016-08-12 00:43:1612786 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012787 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112788 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112789 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112790 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112791}
12792
bnc55ff9da2015-08-19 18:42:3512793// Ensure that we are not allowed to redirect traffic via an alternate protocol
12794// to an unrestricted (port >= 1024) when the original traffic was on a
12795// restricted port (port < 1024). Ensure that we can redirect in all other
12796// cases.
bncd16676a2016-07-20 16:23:0112797TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1112798 HttpRequestInfo unrestricted_port_request;
12799 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512800 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112801 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012802 unrestricted_port_request.traffic_annotation =
12803 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112804
[email protected]d973e99a2012-02-17 21:02:3612805 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112806 StaticSocketDataProvider first_data;
12807 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712808 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112809
12810 MockRead data_reads[] = {
12811 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12812 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612813 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112814 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112815 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712816 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112817
bncb26024382016-06-29 02:39:4512818 SSLSocketDataProvider ssl(ASYNC, OK);
12819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12820
danakj1fd259a02016-04-16 03:17:0912821 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112822
bnc525e175a2016-06-20 12:36:4012823 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312824 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2212825 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2112826 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12827 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212828 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112829 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712830 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
12831 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112832
bnc691fda62016-08-12 00:43:1612833 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112834 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112835
bnc691fda62016-08-12 00:43:1612836 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012837 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112839 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0112840 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112841}
12842
bnc55ff9da2015-08-19 18:42:3512843// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2112844// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
12845// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0112846TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0212847 HttpRequestInfo request;
12848 request.method = "GET";
bncce36dca22015-04-21 22:11:2312849 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012850 request.traffic_annotation =
12851 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0212852
12853 // The alternate protocol request will error out before we attempt to connect,
12854 // so only the standard HTTP request will try to connect.
12855 MockRead data_reads[] = {
12856 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12857 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612858 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0212859 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112860 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712861 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0212862
danakj1fd259a02016-04-16 03:17:0912863 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0212864
bnc525e175a2016-06-20 12:36:4012865 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0212866 session->http_server_properties();
12867 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2112868 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12869 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1212870 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112871 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712872 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12873 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0212874
bnc691fda62016-08-12 00:43:1612875 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0212876 TestCompletionCallback callback;
12877
tfarina42834112016-09-22 13:38:2012878 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0212880 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0112881 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212882
bnc691fda62016-08-12 00:43:1612883 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212884 ASSERT_TRUE(response);
12885 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0212886 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12887
12888 std::string response_data;
bnc691fda62016-08-12 00:43:1612889 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212890 EXPECT_EQ("hello world", response_data);
12891}
12892
bncd16676a2016-07-20 16:23:0112893TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5412894 HttpRequestInfo request;
12895 request.method = "GET";
bncb26024382016-06-29 02:39:4512896 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012897 request.traffic_annotation =
12898 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5412899
12900 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212901 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312902 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212903 MockRead("\r\n"),
12904 MockRead("hello world"),
12905 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12906 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5412907
Ryan Sleevib8d7ea02018-05-07 20:01:0112908 StaticSocketDataProvider first_transaction(data_reads,
12909 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712910 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4512911 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612912 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5412914
bnc032658ba2016-09-26 18:17:1512915 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5412916
Ryan Hamilton0239aac2018-05-19 00:03:1312917 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4512918 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4112919 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5412920
Raul Tambre94493c652019-03-11 17:18:3512921 spdy::SpdySerializedFrame resp(
12922 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312923 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5412924 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112925 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5412926 };
12927
Ryan Sleevib8d7ea02018-05-07 20:01:0112928 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712929 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5412930
[email protected]d973e99a2012-02-17 21:02:3612931 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112932 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5512933 hanging_non_alternate_protocol_socket.set_connect_data(
12934 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0712935 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5512936 &hanging_non_alternate_protocol_socket);
12937
[email protected]49639fa2011-12-20 23:22:4112938 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5412939
danakj1fd259a02016-04-16 03:17:0912940 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812941 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912942 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412943
tfarina42834112016-09-22 13:38:2012944 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112945 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12946 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412947
12948 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212949 ASSERT_TRUE(response);
12950 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5412951 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12952
12953 std::string response_data;
robpercival214763f2016-07-01 23:27:0112954 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412955 EXPECT_EQ("hello world", response_data);
12956
bnc87dcefc2017-05-25 12:47:5812957 trans =
Jeremy Roman0579ed62017-08-29 15:56:1912958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412959
tfarina42834112016-09-22 13:38:2012960 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112961 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12962 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412963
12964 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212965 ASSERT_TRUE(response);
12966 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212967 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5312968 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212969 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5412970
robpercival214763f2016-07-01 23:27:0112971 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412972 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5412973}
12974
bncd16676a2016-07-20 16:23:0112975TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5512976 HttpRequestInfo request;
12977 request.method = "GET";
bncb26024382016-06-29 02:39:4512978 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012979 request.traffic_annotation =
12980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5512981
bncb26024382016-06-29 02:39:4512982 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5512983 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212984 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312985 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212986 MockRead("\r\n"),
12987 MockRead("hello world"),
12988 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12989 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5512990 };
12991
Ryan Sleevib8d7ea02018-05-07 20:01:0112992 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4512993 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5512994
bncb26024382016-06-29 02:39:4512995 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912996 ssl_http11.ssl_info.cert =
12997 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12998 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4512999 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13000
13001 // Second transaction starts an alternative and a non-alternative Job.
13002 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613003 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113004 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813005 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813006 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13007
Ryan Sleevib8d7ea02018-05-07 20:01:0113008 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813009 hanging_socket2.set_connect_data(never_finishing_connect);
13010 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513011
bncb26024382016-06-29 02:39:4513012 // Third transaction starts an alternative and a non-alternative job.
13013 // The non-alternative job hangs, but the alternative one succeeds.
13014 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313015 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513016 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313017 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513018 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513019 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113020 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513021 };
Raul Tambre94493c652019-03-11 17:18:3513022 spdy::SpdySerializedFrame resp1(
13023 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313024 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513025 spdy::SpdySerializedFrame resp2(
13026 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313027 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513028 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113029 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13030 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313031 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513032 };
13033
Ryan Sleevib8d7ea02018-05-07 20:01:0113034 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713035 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513036
bnc032658ba2016-09-26 18:17:1513037 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513038
Ryan Sleevib8d7ea02018-05-07 20:01:0113039 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813040 hanging_socket3.set_connect_data(never_finishing_connect);
13041 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513042
danakj1fd259a02016-04-16 03:17:0913043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113044 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013045 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513046
tfarina42834112016-09-22 13:38:2013047 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13049 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513050
13051 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213052 ASSERT_TRUE(response);
13053 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513054 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13055
13056 std::string response_data;
robpercival214763f2016-07-01 23:27:0113057 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513058 EXPECT_EQ("hello world", response_data);
13059
[email protected]49639fa2011-12-20 23:22:4113060 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013061 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013062 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513064
[email protected]49639fa2011-12-20 23:22:4113065 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013066 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013067 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113068 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513069
robpercival214763f2016-07-01 23:27:0113070 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13071 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513072
13073 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213074 ASSERT_TRUE(response);
13075 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213076 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513077 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213078 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113079 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513080 EXPECT_EQ("hello!", response_data);
13081
13082 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213083 ASSERT_TRUE(response);
13084 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213085 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513086 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213087 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113088 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513089 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513090}
13091
bncd16676a2016-07-20 16:23:0113092TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313093 session_deps_.host_resolver->set_synchronous_mode(true);
13094
[email protected]2d6728692011-03-12 01:39:5513095 HttpRequestInfo request;
13096 request.method = "GET";
bncb26024382016-06-29 02:39:4513097 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013098 request.traffic_annotation =
13099 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513100
13101 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213102 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313103 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213104 MockRead("\r\n"),
13105 MockRead("hello world"),
13106 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13107 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513108 };
13109
Ryan Sleevib8d7ea02018-05-07 20:01:0113110 StaticSocketDataProvider first_transaction(data_reads,
13111 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713112 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513113
[email protected]8ddf8322012-02-23 18:08:0613114 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913115 ssl.ssl_info.cert =
13116 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13117 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513119
[email protected]d973e99a2012-02-17 21:02:3613120 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113121 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513122 hanging_alternate_protocol_socket.set_connect_data(
13123 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713124 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513125 &hanging_alternate_protocol_socket);
13126
bncb26024382016-06-29 02:39:4513127 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113128 StaticSocketDataProvider second_transaction(data_reads,
13129 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813130 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513132
[email protected]49639fa2011-12-20 23:22:4113133 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513134
danakj1fd259a02016-04-16 03:17:0913135 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813136 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913137 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513138
tfarina42834112016-09-22 13:38:2013139 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113140 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13141 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513142
13143 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213144 ASSERT_TRUE(response);
13145 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513146 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13147
13148 std::string response_data;
robpercival214763f2016-07-01 23:27:0113149 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513150 EXPECT_EQ("hello world", response_data);
13151
bnc87dcefc2017-05-25 12:47:5813152 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913153 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513154
tfarina42834112016-09-22 13:38:2013155 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13157 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513158
13159 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213160 ASSERT_TRUE(response);
13161 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13163 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213164 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513165
robpercival214763f2016-07-01 23:27:0113166 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513167 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513168}
13169
bnc2e884782016-08-11 19:45:1913170// Test that proxy is resolved using the origin url,
13171// regardless of the alternative server.
13172TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13173 // Configure proxy to bypass www.example.org, which is the origin URL.
13174 ProxyConfig proxy_config;
13175 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13176 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913177 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13178 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913179
13180 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913181 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913182 &capturing_proxy_resolver);
13183
13184 TestNetLog net_log;
13185
Bence Béky53a5aef2018-03-29 21:54:1213186 session_deps_.proxy_resolution_service =
13187 std::make_unique<ProxyResolutionService>(
13188 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13189 &net_log);
bnc2e884782016-08-11 19:45:1913190
13191 session_deps_.net_log = &net_log;
13192
13193 // Configure alternative service with a hostname that is not bypassed by the
13194 // proxy.
13195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13196 HttpServerProperties* http_server_properties =
13197 session->http_server_properties();
13198 url::SchemeHostPort server("https", "www.example.org", 443);
13199 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113200 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913201 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113202 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713203 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913204
13205 // Non-alternative job should hang.
13206 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113207 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913208 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13209 session_deps_.socket_factory->AddSocketDataProvider(
13210 &hanging_alternate_protocol_socket);
13211
bnc032658ba2016-09-26 18:17:1513212 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913213
13214 HttpRequestInfo request;
13215 request.method = "GET";
13216 request.url = GURL("https://www.example.org/");
13217 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013218 request.traffic_annotation =
13219 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913220
Ryan Hamilton0239aac2018-05-19 00:03:1313221 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913222 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13223
13224 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13225
Ryan Hamilton0239aac2018-05-19 00:03:1313226 spdy::SpdySerializedFrame resp(
13227 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13228 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913229 MockRead spdy_reads[] = {
13230 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13231 };
13232
Ryan Sleevib8d7ea02018-05-07 20:01:0113233 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913234 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13235
13236 TestCompletionCallback callback;
13237
13238 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13239
tfarina42834112016-09-22 13:38:2013240 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913241 EXPECT_THAT(callback.GetResult(rv), IsOk());
13242
13243 const HttpResponseInfo* response = trans.GetResponseInfo();
13244 ASSERT_TRUE(response);
13245 ASSERT_TRUE(response->headers);
13246 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13247 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213248 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913249
13250 std::string response_data;
13251 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13252 EXPECT_EQ("hello!", response_data);
13253
13254 // Origin host bypasses proxy, no resolution should have happened.
13255 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13256}
13257
bncd16676a2016-07-20 16:23:0113258TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113259 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213260 proxy_config.set_auto_detect(true);
13261 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113262
sammc5dd160c2015-04-02 02:43:1313263 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913264 session_deps_.proxy_resolution_service =
13265 std::make_unique<ProxyResolutionService>(
13266 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13267 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13268 std::make_unique<CapturingProxyResolverFactory>(
13269 &capturing_proxy_resolver),
13270 nullptr);
vishal.b62985ca92015-04-17 08:45:5113271 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713272 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113273
13274 HttpRequestInfo request;
13275 request.method = "GET";
bncb26024382016-06-29 02:39:4513276 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013277 request.traffic_annotation =
13278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113279
13280 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213281 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313282 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213283 MockRead("\r\n"),
13284 MockRead("hello world"),
13285 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13286 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113287 };
13288
Ryan Sleevib8d7ea02018-05-07 20:01:0113289 StaticSocketDataProvider first_transaction(data_reads,
13290 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713291 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513292 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613293 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113295
bnc032658ba2016-09-26 18:17:1513296 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113297
Ryan Hamilton0239aac2018-05-19 00:03:1313298 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513299 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113300 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313301 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513302 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13303 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313304 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113305 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113306 };
13307
[email protected]d911f1b2010-05-05 22:39:4213308 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13309
Raul Tambre94493c652019-03-11 17:18:3513310 spdy::SpdySerializedFrame resp(
13311 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313312 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113313 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113314 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13315 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113316 };
13317
Ryan Sleevib8d7ea02018-05-07 20:01:0113318 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713319 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113320
[email protected]d973e99a2012-02-17 21:02:3613321 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113322 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513323 hanging_non_alternate_protocol_socket.set_connect_data(
13324 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713325 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513326 &hanging_non_alternate_protocol_socket);
13327
[email protected]49639fa2011-12-20 23:22:4113328 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113329
danakj1fd259a02016-04-16 03:17:0913330 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813331 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113333
tfarina42834112016-09-22 13:38:2013334 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113335 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13336 EXPECT_THAT(callback.WaitForResult(), IsOk());
13337
13338 const HttpResponseInfo* response = trans->GetResponseInfo();
13339 ASSERT_TRUE(response);
13340 ASSERT_TRUE(response->headers);
13341 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13342 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213343 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113344
13345 std::string response_data;
13346 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13347 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113348
bnc87dcefc2017-05-25 12:47:5813349 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913350 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113351
tfarina42834112016-09-22 13:38:2013352 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113353 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13354 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113355
mmenkea2dcd3bf2016-08-16 21:49:4113356 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213357 ASSERT_TRUE(response);
13358 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213359 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313360 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213361 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113362
robpercival214763f2016-07-01 23:27:0113363 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113364 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513365 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13366 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313367 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313368 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313369 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113370
[email protected]029c83b62013-01-24 05:28:2013371 LoadTimingInfo load_timing_info;
13372 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13373 TestLoadTimingNotReusedWithPac(load_timing_info,
13374 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113375}
[email protected]631f1322010-04-30 17:59:1113376
bncd16676a2016-07-20 16:23:0113377TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813378 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413379 HttpRequestInfo request;
13380 request.method = "GET";
bncb26024382016-06-29 02:39:4513381 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013382 request.traffic_annotation =
13383 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413384
13385 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213386 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313387 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213388 MockRead("\r\n"),
13389 MockRead("hello world"),
13390 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413391 };
13392
Ryan Sleevib8d7ea02018-05-07 20:01:0113393 StaticSocketDataProvider first_transaction(data_reads,
13394 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713395 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513396 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613397 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413399
bnc032658ba2016-09-26 18:17:1513400 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413401
Ryan Hamilton0239aac2018-05-19 00:03:1313402 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513403 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113404 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413405
Raul Tambre94493c652019-03-11 17:18:3513406 spdy::SpdySerializedFrame resp(
13407 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313408 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413409 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113410 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413411 };
13412
Ryan Sleevib8d7ea02018-05-07 20:01:0113413 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713414 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413415
[email protected]83039bb2011-12-09 18:43:5513416 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413417
danakj1fd259a02016-04-16 03:17:0913418 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413419
bnc87dcefc2017-05-25 12:47:5813420 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913421 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413422
tfarina42834112016-09-22 13:38:2013423 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113424 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13425 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413426
13427 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213428 ASSERT_TRUE(response);
13429 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413430 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13431
13432 std::string response_data;
robpercival214763f2016-07-01 23:27:0113433 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413434 EXPECT_EQ("hello world", response_data);
13435
13436 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513437 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013438 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113439 PRIVACY_MODE_DISABLED,
13440 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2713441 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213442 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813443
bnc87dcefc2017-05-25 12:47:5813444 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913445 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413446
tfarina42834112016-09-22 13:38:2013447 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113448 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13449 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413450
13451 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213452 ASSERT_TRUE(response);
13453 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213454 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313455 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213456 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413457
robpercival214763f2016-07-01 23:27:0113458 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413459 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213460}
13461
[email protected]044de0642010-06-17 10:42:1513462// GenerateAuthToken is a mighty big test.
13463// It tests all permutation of GenerateAuthToken behavior:
13464// - Synchronous and Asynchronous completion.
13465// - OK or error on completion.
13466// - Direct connection, non-authenticating proxy, and authenticating proxy.
13467// - HTTP or HTTPS backend (to include proxy tunneling).
13468// - Non-authenticating and authenticating backend.
13469//
[email protected]fe3b7dc2012-02-03 19:52:0913470// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513471// problems generating an auth token for an authenticating proxy, we don't
13472// need to test all permutations of the backend server).
13473//
13474// The test proceeds by going over each of the configuration cases, and
13475// potentially running up to three rounds in each of the tests. The TestConfig
13476// specifies both the configuration for the test as well as the expectations
13477// for the results.
bncd16676a2016-07-20 16:23:0113478TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013479 static const char kServer[] = "http://www.example.com";
13480 static const char kSecureServer[] = "https://www.example.com";
13481 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513482
13483 enum AuthTiming {
13484 AUTH_NONE,
13485 AUTH_SYNC,
13486 AUTH_ASYNC,
13487 };
13488
13489 const MockWrite kGet(
13490 "GET / HTTP/1.1\r\n"
13491 "Host: www.example.com\r\n"
13492 "Connection: keep-alive\r\n\r\n");
13493 const MockWrite kGetProxy(
13494 "GET http://www.example.com/ HTTP/1.1\r\n"
13495 "Host: www.example.com\r\n"
13496 "Proxy-Connection: keep-alive\r\n\r\n");
13497 const MockWrite kGetAuth(
13498 "GET / HTTP/1.1\r\n"
13499 "Host: www.example.com\r\n"
13500 "Connection: keep-alive\r\n"
13501 "Authorization: auth_token\r\n\r\n");
13502 const MockWrite kGetProxyAuth(
13503 "GET http://www.example.com/ HTTP/1.1\r\n"
13504 "Host: www.example.com\r\n"
13505 "Proxy-Connection: keep-alive\r\n"
13506 "Proxy-Authorization: auth_token\r\n\r\n");
13507 const MockWrite kGetAuthThroughProxy(
13508 "GET http://www.example.com/ HTTP/1.1\r\n"
13509 "Host: www.example.com\r\n"
13510 "Proxy-Connection: keep-alive\r\n"
13511 "Authorization: auth_token\r\n\r\n");
13512 const MockWrite kGetAuthWithProxyAuth(
13513 "GET http://www.example.com/ HTTP/1.1\r\n"
13514 "Host: www.example.com\r\n"
13515 "Proxy-Connection: keep-alive\r\n"
13516 "Proxy-Authorization: auth_token\r\n"
13517 "Authorization: auth_token\r\n\r\n");
13518 const MockWrite kConnect(
13519 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713520 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513521 "Proxy-Connection: keep-alive\r\n\r\n");
13522 const MockWrite kConnectProxyAuth(
13523 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713524 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513525 "Proxy-Connection: keep-alive\r\n"
13526 "Proxy-Authorization: auth_token\r\n\r\n");
13527
13528 const MockRead kSuccess(
13529 "HTTP/1.1 200 OK\r\n"
13530 "Content-Type: text/html; charset=iso-8859-1\r\n"
13531 "Content-Length: 3\r\n\r\n"
13532 "Yes");
13533 const MockRead kFailure(
13534 "Should not be called.");
13535 const MockRead kServerChallenge(
13536 "HTTP/1.1 401 Unauthorized\r\n"
13537 "WWW-Authenticate: Mock realm=server\r\n"
13538 "Content-Type: text/html; charset=iso-8859-1\r\n"
13539 "Content-Length: 14\r\n\r\n"
13540 "Unauthorized\r\n");
13541 const MockRead kProxyChallenge(
13542 "HTTP/1.1 407 Unauthorized\r\n"
13543 "Proxy-Authenticate: Mock realm=proxy\r\n"
13544 "Proxy-Connection: close\r\n"
13545 "Content-Type: text/html; charset=iso-8859-1\r\n"
13546 "Content-Length: 14\r\n\r\n"
13547 "Unauthorized\r\n");
13548 const MockRead kProxyConnected(
13549 "HTTP/1.1 200 Connection Established\r\n\r\n");
13550
13551 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13552 // no constructors, but the C++ compiler on Windows warns about
13553 // unspecified data in compound literals. So, moved to using constructors,
13554 // and TestRound's created with the default constructor should not be used.
13555 struct TestRound {
13556 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513557 : expected_rv(ERR_UNEXPECTED),
13558 extra_write(nullptr),
13559 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313560 TestRound(const MockWrite& write_arg,
13561 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513562 int expected_rv_arg)
13563 : write(write_arg),
13564 read(read_arg),
13565 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513566 extra_write(nullptr),
13567 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513568 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13569 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113570 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513571 : write(write_arg),
13572 read(read_arg),
13573 expected_rv(expected_rv_arg),
13574 extra_write(extra_write_arg),
13575 extra_read(extra_read_arg) {
13576 }
13577 MockWrite write;
13578 MockRead read;
13579 int expected_rv;
13580 const MockWrite* extra_write;
13581 const MockRead* extra_read;
13582 };
13583
13584 static const int kNoSSL = 500;
13585
13586 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113587 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113588 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513589 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113590 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113591 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513592 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113593 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513594 int num_auth_rounds;
13595 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613596 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513597 } test_configs[] = {
asankac93076192016-10-03 15:46:0213598 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113599 {__LINE__,
13600 nullptr,
asankac93076192016-10-03 15:46:0213601 AUTH_NONE,
13602 OK,
13603 kServer,
13604 AUTH_NONE,
13605 OK,
13606 1,
13607 kNoSSL,
13608 {TestRound(kGet, kSuccess, OK)}},
13609 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113610 {__LINE__,
13611 nullptr,
asankac93076192016-10-03 15:46:0213612 AUTH_NONE,
13613 OK,
13614 kServer,
13615 AUTH_SYNC,
13616 OK,
13617 2,
13618 kNoSSL,
13619 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513620 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113621 {__LINE__,
13622 nullptr,
asankac93076192016-10-03 15:46:0213623 AUTH_NONE,
13624 OK,
13625 kServer,
13626 AUTH_SYNC,
13627 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613628 3,
13629 kNoSSL,
13630 {TestRound(kGet, kServerChallenge, OK),
13631 TestRound(kGet, kServerChallenge, OK),
13632 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113633 {__LINE__,
13634 nullptr,
asankae2257db2016-10-11 22:03:1613635 AUTH_NONE,
13636 OK,
13637 kServer,
13638 AUTH_SYNC,
13639 ERR_UNSUPPORTED_AUTH_SCHEME,
13640 2,
13641 kNoSSL,
13642 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113643 {__LINE__,
13644 nullptr,
asankae2257db2016-10-11 22:03:1613645 AUTH_NONE,
13646 OK,
13647 kServer,
13648 AUTH_SYNC,
13649 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13650 2,
13651 kNoSSL,
13652 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113653 {__LINE__,
13654 kProxy,
asankae2257db2016-10-11 22:03:1613655 AUTH_SYNC,
13656 ERR_FAILED,
13657 kServer,
13658 AUTH_NONE,
13659 OK,
13660 2,
13661 kNoSSL,
13662 {TestRound(kGetProxy, kProxyChallenge, OK),
13663 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113664 {__LINE__,
13665 kProxy,
asankae2257db2016-10-11 22:03:1613666 AUTH_ASYNC,
13667 ERR_FAILED,
13668 kServer,
13669 AUTH_NONE,
13670 OK,
13671 2,
13672 kNoSSL,
13673 {TestRound(kGetProxy, kProxyChallenge, OK),
13674 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113675 {__LINE__,
13676 nullptr,
asankae2257db2016-10-11 22:03:1613677 AUTH_NONE,
13678 OK,
13679 kServer,
13680 AUTH_SYNC,
13681 ERR_FAILED,
asankac93076192016-10-03 15:46:0213682 2,
13683 kNoSSL,
13684 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613685 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113686 {__LINE__,
13687 nullptr,
asankae2257db2016-10-11 22:03:1613688 AUTH_NONE,
13689 OK,
13690 kServer,
13691 AUTH_ASYNC,
13692 ERR_FAILED,
13693 2,
13694 kNoSSL,
13695 {TestRound(kGet, kServerChallenge, OK),
13696 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113697 {__LINE__,
13698 nullptr,
asankac93076192016-10-03 15:46:0213699 AUTH_NONE,
13700 OK,
13701 kServer,
13702 AUTH_ASYNC,
13703 OK,
13704 2,
13705 kNoSSL,
13706 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513707 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113708 {__LINE__,
13709 nullptr,
asankac93076192016-10-03 15:46:0213710 AUTH_NONE,
13711 OK,
13712 kServer,
13713 AUTH_ASYNC,
13714 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613715 3,
asankac93076192016-10-03 15:46:0213716 kNoSSL,
13717 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613718 // The second round uses a HttpAuthHandlerMock that always succeeds.
13719 TestRound(kGet, kServerChallenge, OK),
13720 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213721 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113722 {__LINE__,
13723 kProxy,
asankac93076192016-10-03 15:46:0213724 AUTH_NONE,
13725 OK,
13726 kServer,
13727 AUTH_NONE,
13728 OK,
13729 1,
13730 kNoSSL,
13731 {TestRound(kGetProxy, kSuccess, OK)}},
13732 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113733 {__LINE__,
13734 kProxy,
asankac93076192016-10-03 15:46:0213735 AUTH_NONE,
13736 OK,
13737 kServer,
13738 AUTH_SYNC,
13739 OK,
13740 2,
13741 kNoSSL,
13742 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513743 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113744 {__LINE__,
13745 kProxy,
asankac93076192016-10-03 15:46:0213746 AUTH_NONE,
13747 OK,
13748 kServer,
13749 AUTH_SYNC,
13750 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613751 3,
asankac93076192016-10-03 15:46:0213752 kNoSSL,
13753 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613754 TestRound(kGetProxy, kServerChallenge, OK),
13755 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113756 {__LINE__,
13757 kProxy,
asankac93076192016-10-03 15:46:0213758 AUTH_NONE,
13759 OK,
13760 kServer,
13761 AUTH_ASYNC,
13762 OK,
13763 2,
13764 kNoSSL,
13765 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513766 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113767 {__LINE__,
13768 kProxy,
asankac93076192016-10-03 15:46:0213769 AUTH_NONE,
13770 OK,
13771 kServer,
13772 AUTH_ASYNC,
13773 ERR_INVALID_AUTH_CREDENTIALS,
13774 2,
13775 kNoSSL,
13776 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613777 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213778 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113779 {__LINE__,
13780 kProxy,
asankac93076192016-10-03 15:46:0213781 AUTH_SYNC,
13782 OK,
13783 kServer,
13784 AUTH_NONE,
13785 OK,
13786 2,
13787 kNoSSL,
13788 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513789 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113790 {__LINE__,
13791 kProxy,
asankac93076192016-10-03 15:46:0213792 AUTH_SYNC,
13793 ERR_INVALID_AUTH_CREDENTIALS,
13794 kServer,
13795 AUTH_NONE,
13796 OK,
13797 2,
13798 kNoSSL,
13799 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613800 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113801 {__LINE__,
13802 kProxy,
asankac93076192016-10-03 15:46:0213803 AUTH_ASYNC,
13804 OK,
13805 kServer,
13806 AUTH_NONE,
13807 OK,
13808 2,
13809 kNoSSL,
13810 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513811 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113812 {__LINE__,
13813 kProxy,
asankac93076192016-10-03 15:46:0213814 AUTH_ASYNC,
13815 ERR_INVALID_AUTH_CREDENTIALS,
13816 kServer,
13817 AUTH_NONE,
13818 OK,
13819 2,
13820 kNoSSL,
13821 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613822 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113823 {__LINE__,
13824 kProxy,
13825 AUTH_ASYNC,
13826 ERR_INVALID_AUTH_CREDENTIALS,
13827 kServer,
13828 AUTH_NONE,
13829 OK,
13830 3,
13831 kNoSSL,
13832 {TestRound(kGetProxy, kProxyChallenge, OK),
13833 TestRound(kGetProxy, kProxyChallenge, OK),
13834 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213835 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113836 {__LINE__,
13837 kProxy,
asankac93076192016-10-03 15:46:0213838 AUTH_SYNC,
13839 OK,
13840 kServer,
13841 AUTH_SYNC,
13842 OK,
13843 3,
13844 kNoSSL,
13845 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513846 TestRound(kGetProxyAuth, kServerChallenge, OK),
13847 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113848 {__LINE__,
13849 kProxy,
asankac93076192016-10-03 15:46:0213850 AUTH_SYNC,
13851 OK,
13852 kServer,
13853 AUTH_SYNC,
13854 ERR_INVALID_AUTH_CREDENTIALS,
13855 3,
13856 kNoSSL,
13857 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513858 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613859 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113860 {__LINE__,
13861 kProxy,
asankac93076192016-10-03 15:46:0213862 AUTH_ASYNC,
13863 OK,
13864 kServer,
13865 AUTH_SYNC,
13866 OK,
13867 3,
13868 kNoSSL,
13869 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513870 TestRound(kGetProxyAuth, kServerChallenge, OK),
13871 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113872 {__LINE__,
13873 kProxy,
asankac93076192016-10-03 15:46:0213874 AUTH_ASYNC,
13875 OK,
13876 kServer,
13877 AUTH_SYNC,
13878 ERR_INVALID_AUTH_CREDENTIALS,
13879 3,
13880 kNoSSL,
13881 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513882 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613883 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113884 {__LINE__,
13885 kProxy,
asankac93076192016-10-03 15:46:0213886 AUTH_SYNC,
13887 OK,
13888 kServer,
13889 AUTH_ASYNC,
13890 OK,
13891 3,
13892 kNoSSL,
13893 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513894 TestRound(kGetProxyAuth, kServerChallenge, OK),
13895 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113896 {__LINE__,
13897 kProxy,
13898 AUTH_SYNC,
13899 ERR_INVALID_AUTH_CREDENTIALS,
13900 kServer,
13901 AUTH_ASYNC,
13902 OK,
13903 4,
13904 kNoSSL,
13905 {TestRound(kGetProxy, kProxyChallenge, OK),
13906 TestRound(kGetProxy, kProxyChallenge, OK),
13907 TestRound(kGetProxyAuth, kServerChallenge, OK),
13908 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
13909 {__LINE__,
13910 kProxy,
asankac93076192016-10-03 15:46:0213911 AUTH_SYNC,
13912 OK,
13913 kServer,
13914 AUTH_ASYNC,
13915 ERR_INVALID_AUTH_CREDENTIALS,
13916 3,
13917 kNoSSL,
13918 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513919 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613920 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113921 {__LINE__,
13922 kProxy,
asankac93076192016-10-03 15:46:0213923 AUTH_ASYNC,
13924 OK,
13925 kServer,
13926 AUTH_ASYNC,
13927 OK,
13928 3,
13929 kNoSSL,
13930 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513931 TestRound(kGetProxyAuth, kServerChallenge, OK),
13932 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113933 {__LINE__,
13934 kProxy,
asankac93076192016-10-03 15:46:0213935 AUTH_ASYNC,
13936 OK,
13937 kServer,
13938 AUTH_ASYNC,
13939 ERR_INVALID_AUTH_CREDENTIALS,
13940 3,
13941 kNoSSL,
13942 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513943 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613944 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113945 {__LINE__,
13946 kProxy,
13947 AUTH_ASYNC,
13948 ERR_INVALID_AUTH_CREDENTIALS,
13949 kServer,
13950 AUTH_ASYNC,
13951 ERR_INVALID_AUTH_CREDENTIALS,
13952 4,
13953 kNoSSL,
13954 {TestRound(kGetProxy, kProxyChallenge, OK),
13955 TestRound(kGetProxy, kProxyChallenge, OK),
13956 TestRound(kGetProxyAuth, kServerChallenge, OK),
13957 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213958 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113959 {__LINE__,
13960 nullptr,
asankac93076192016-10-03 15:46:0213961 AUTH_NONE,
13962 OK,
13963 kSecureServer,
13964 AUTH_NONE,
13965 OK,
13966 1,
13967 0,
13968 {TestRound(kGet, kSuccess, OK)}},
13969 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113970 {__LINE__,
13971 nullptr,
asankac93076192016-10-03 15:46:0213972 AUTH_NONE,
13973 OK,
13974 kSecureServer,
13975 AUTH_SYNC,
13976 OK,
13977 2,
13978 0,
13979 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513980 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113981 {__LINE__,
13982 nullptr,
asankac93076192016-10-03 15:46:0213983 AUTH_NONE,
13984 OK,
13985 kSecureServer,
13986 AUTH_SYNC,
13987 ERR_INVALID_AUTH_CREDENTIALS,
13988 2,
13989 0,
asankae2257db2016-10-11 22:03:1613990 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113991 {__LINE__,
13992 nullptr,
asankac93076192016-10-03 15:46:0213993 AUTH_NONE,
13994 OK,
13995 kSecureServer,
13996 AUTH_ASYNC,
13997 OK,
13998 2,
13999 0,
14000 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514001 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114002 {__LINE__,
14003 nullptr,
asankac93076192016-10-03 15:46:0214004 AUTH_NONE,
14005 OK,
14006 kSecureServer,
14007 AUTH_ASYNC,
14008 ERR_INVALID_AUTH_CREDENTIALS,
14009 2,
14010 0,
asankae2257db2016-10-11 22:03:1614011 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214012 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114013 {__LINE__,
14014 kProxy,
asankac93076192016-10-03 15:46:0214015 AUTH_NONE,
14016 OK,
14017 kSecureServer,
14018 AUTH_NONE,
14019 OK,
14020 1,
14021 0,
14022 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14023 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114024 {__LINE__,
14025 kProxy,
asankac93076192016-10-03 15:46:0214026 AUTH_NONE,
14027 OK,
14028 kSecureServer,
14029 AUTH_SYNC,
14030 OK,
14031 2,
14032 0,
14033 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514034 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114035 {__LINE__,
14036 kProxy,
asankac93076192016-10-03 15:46:0214037 AUTH_NONE,
14038 OK,
14039 kSecureServer,
14040 AUTH_SYNC,
14041 ERR_INVALID_AUTH_CREDENTIALS,
14042 2,
14043 0,
14044 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614045 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114046 {__LINE__,
14047 kProxy,
asankac93076192016-10-03 15:46:0214048 AUTH_NONE,
14049 OK,
14050 kSecureServer,
14051 AUTH_ASYNC,
14052 OK,
14053 2,
14054 0,
14055 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514056 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114057 {__LINE__,
14058 kProxy,
asankac93076192016-10-03 15:46:0214059 AUTH_NONE,
14060 OK,
14061 kSecureServer,
14062 AUTH_ASYNC,
14063 ERR_INVALID_AUTH_CREDENTIALS,
14064 2,
14065 0,
14066 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614067 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214068 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114069 {__LINE__,
14070 kProxy,
asankac93076192016-10-03 15:46:0214071 AUTH_SYNC,
14072 OK,
14073 kSecureServer,
14074 AUTH_NONE,
14075 OK,
14076 2,
14077 1,
14078 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514079 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114080 {__LINE__,
14081 kProxy,
asankac93076192016-10-03 15:46:0214082 AUTH_SYNC,
14083 ERR_INVALID_AUTH_CREDENTIALS,
14084 kSecureServer,
14085 AUTH_NONE,
14086 OK,
14087 2,
14088 kNoSSL,
14089 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614090 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114091 {__LINE__,
14092 kProxy,
asankae2257db2016-10-11 22:03:1614093 AUTH_SYNC,
14094 ERR_UNSUPPORTED_AUTH_SCHEME,
14095 kSecureServer,
14096 AUTH_NONE,
14097 OK,
14098 2,
14099 kNoSSL,
14100 {TestRound(kConnect, kProxyChallenge, OK),
14101 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114102 {__LINE__,
14103 kProxy,
asankae2257db2016-10-11 22:03:1614104 AUTH_SYNC,
14105 ERR_UNEXPECTED,
14106 kSecureServer,
14107 AUTH_NONE,
14108 OK,
14109 2,
14110 kNoSSL,
14111 {TestRound(kConnect, kProxyChallenge, OK),
14112 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114113 {__LINE__,
14114 kProxy,
asankac93076192016-10-03 15:46:0214115 AUTH_ASYNC,
14116 OK,
14117 kSecureServer,
14118 AUTH_NONE,
14119 OK,
14120 2,
14121 1,
14122 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514123 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114124 {__LINE__,
14125 kProxy,
asankac93076192016-10-03 15:46:0214126 AUTH_ASYNC,
14127 ERR_INVALID_AUTH_CREDENTIALS,
14128 kSecureServer,
14129 AUTH_NONE,
14130 OK,
14131 2,
14132 kNoSSL,
14133 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614134 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214135 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114136 {__LINE__,
14137 kProxy,
asankac93076192016-10-03 15:46:0214138 AUTH_SYNC,
14139 OK,
14140 kSecureServer,
14141 AUTH_SYNC,
14142 OK,
14143 3,
14144 1,
14145 {TestRound(kConnect, kProxyChallenge, OK),
14146 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14147 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514148 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114149 {__LINE__,
14150 kProxy,
asankac93076192016-10-03 15:46:0214151 AUTH_SYNC,
14152 OK,
14153 kSecureServer,
14154 AUTH_SYNC,
14155 ERR_INVALID_AUTH_CREDENTIALS,
14156 3,
14157 1,
14158 {TestRound(kConnect, kProxyChallenge, OK),
14159 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14160 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614161 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114162 {__LINE__,
14163 kProxy,
asankac93076192016-10-03 15:46:0214164 AUTH_ASYNC,
14165 OK,
14166 kSecureServer,
14167 AUTH_SYNC,
14168 OK,
14169 3,
14170 1,
14171 {TestRound(kConnect, kProxyChallenge, OK),
14172 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14173 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514174 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114175 {__LINE__,
14176 kProxy,
asankac93076192016-10-03 15:46:0214177 AUTH_ASYNC,
14178 OK,
14179 kSecureServer,
14180 AUTH_SYNC,
14181 ERR_INVALID_AUTH_CREDENTIALS,
14182 3,
14183 1,
14184 {TestRound(kConnect, kProxyChallenge, OK),
14185 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14186 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614187 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114188 {__LINE__,
14189 kProxy,
asankac93076192016-10-03 15:46:0214190 AUTH_SYNC,
14191 OK,
14192 kSecureServer,
14193 AUTH_ASYNC,
14194 OK,
14195 3,
14196 1,
14197 {TestRound(kConnect, kProxyChallenge, OK),
14198 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14199 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514200 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114201 {__LINE__,
14202 kProxy,
asankac93076192016-10-03 15:46:0214203 AUTH_SYNC,
14204 OK,
14205 kSecureServer,
14206 AUTH_ASYNC,
14207 ERR_INVALID_AUTH_CREDENTIALS,
14208 3,
14209 1,
14210 {TestRound(kConnect, kProxyChallenge, OK),
14211 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14212 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614213 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114214 {__LINE__,
14215 kProxy,
asankac93076192016-10-03 15:46:0214216 AUTH_ASYNC,
14217 OK,
14218 kSecureServer,
14219 AUTH_ASYNC,
14220 OK,
14221 3,
14222 1,
14223 {TestRound(kConnect, kProxyChallenge, OK),
14224 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14225 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514226 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114227 {__LINE__,
14228 kProxy,
asankac93076192016-10-03 15:46:0214229 AUTH_ASYNC,
14230 OK,
14231 kSecureServer,
14232 AUTH_ASYNC,
14233 ERR_INVALID_AUTH_CREDENTIALS,
14234 3,
14235 1,
14236 {TestRound(kConnect, kProxyChallenge, OK),
14237 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14238 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614239 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114240 {__LINE__,
14241 kProxy,
14242 AUTH_ASYNC,
14243 ERR_INVALID_AUTH_CREDENTIALS,
14244 kSecureServer,
14245 AUTH_ASYNC,
14246 ERR_INVALID_AUTH_CREDENTIALS,
14247 4,
14248 2,
14249 {TestRound(kConnect, kProxyChallenge, OK),
14250 TestRound(kConnect, kProxyChallenge, OK),
14251 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14252 &kServerChallenge),
14253 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514254 };
14255
asanka463ca4262016-11-16 02:34:3114256 for (const auto& test_config : test_configs) {
14257 SCOPED_TRACE(::testing::Message() << "Test config at "
14258 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814259 HttpAuthHandlerMock::Factory* auth_factory(
14260 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714261 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914262 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614263
14264 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514265 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114266 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814267 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14268 std::string auth_challenge = "Mock realm=proxy";
14269 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414270 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14271 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814272 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014273 empty_ssl_info, origin,
14274 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814275 auth_handler->SetGenerateExpectation(
14276 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114277 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814278 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14279 }
[email protected]044de0642010-06-17 10:42:1514280 }
14281 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014282 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514283 std::string auth_challenge = "Mock realm=server";
14284 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414285 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14286 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514287 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014288 empty_ssl_info, origin,
14289 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514290 auth_handler->SetGenerateExpectation(
14291 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114292 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814293 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614294
14295 // The second handler always succeeds. It should only be used where there
14296 // are multiple auth sessions for server auth in the same network
14297 // transaction using the same auth scheme.
14298 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914299 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614300 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14301 empty_ssl_info, origin,
14302 NetLogWithSource());
14303 second_handler->SetGenerateExpectation(true, OK);
14304 auth_factory->AddMockHandler(second_handler.release(),
14305 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514306 }
14307 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914308 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914309 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14310 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514311 } else {
Bence Béky53a5aef2018-03-29 21:54:1214312 session_deps_.proxy_resolution_service =
14313 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514314 }
14315
14316 HttpRequestInfo request;
14317 request.method = "GET";
14318 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1014319 request.traffic_annotation =
14320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514321
danakj1fd259a02016-04-16 03:17:0914322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514323
rchcb68dc62015-05-21 04:45:3614324 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14325
14326 std::vector<std::vector<MockRead>> mock_reads(1);
14327 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514328 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214329 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514330 const TestRound& read_write_round = test_config.rounds[round];
14331
14332 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614333 mock_reads.back().push_back(read_write_round.read);
14334 mock_writes.back().push_back(read_write_round.write);
14335
14336 // kProxyChallenge uses Proxy-Connection: close which means that the
14337 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414338 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614339 mock_reads.push_back(std::vector<MockRead>());
14340 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514341 }
14342
rchcb68dc62015-05-21 04:45:3614343 if (read_write_round.extra_read) {
14344 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514345 }
rchcb68dc62015-05-21 04:45:3614346 if (read_write_round.extra_write) {
14347 mock_writes.back().push_back(*read_write_round.extra_write);
14348 }
[email protected]044de0642010-06-17 10:42:1514349
14350 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514351 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714352 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514353 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614354 }
[email protected]044de0642010-06-17 10:42:1514355
danakj1fd259a02016-04-16 03:17:0914356 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614357 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914358 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114359 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614360 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214361 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614362 }
14363
mmenkecc2298e2015-12-07 18:20:1814364 // Transaction must be created after DataProviders, so it's destroyed before
14365 // they are as well.
14366 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14367
rchcb68dc62015-05-21 04:45:3614368 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214369 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614370 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514371 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114372 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514373 int rv;
14374 if (round == 0) {
tfarina42834112016-09-22 13:38:2014375 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514376 } else {
[email protected]49639fa2011-12-20 23:22:4114377 rv = trans.RestartWithAuth(
14378 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514379 }
14380 if (rv == ERR_IO_PENDING)
14381 rv = callback.WaitForResult();
14382
14383 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614384 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014385 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514386 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514387 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14388 continue;
14389 }
14390 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814391 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514392 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814393 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614394 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514395 }
14396 }
[email protected]e5ae96a2010-04-14 20:12:4514397 }
14398}
14399
bncd16676a2016-07-20 16:23:0114400TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414401 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414402 HttpAuthHandlerMock::Factory* auth_factory(
14403 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714404 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214405 session_deps_.proxy_resolution_service =
14406 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714407 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414408
14409 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14410 auth_handler->set_connection_based(true);
14411 std::string auth_challenge = "Mock realm=server";
14412 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414413 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14414 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914415 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414416 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014417 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814418 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414419
[email protected]c871bce92010-07-15 21:51:1414420 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514421 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414422 HttpRequestInfo request;
14423 request.method = "GET";
14424 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1014425 request.traffic_annotation =
14426 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714427
danakj1fd259a02016-04-16 03:17:0914428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014429
14430 // Use a TCP Socket Pool with only one connection per group. This is used
14431 // to validate that the TCP socket is not released to the pool between
14432 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214433 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614434 CommonConnectJobParams common_connect_job_params(
14435 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814436 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914437 50, // Max sockets for pool
14438 1, // Max sockets per group
14439 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614440 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5214441 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1914442 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014443 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14444 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814445 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014446
bnc691fda62016-08-12 00:43:1614447 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114448 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414449
14450 const MockWrite kGet(
14451 "GET / HTTP/1.1\r\n"
14452 "Host: www.example.com\r\n"
14453 "Connection: keep-alive\r\n\r\n");
14454 const MockWrite kGetAuth(
14455 "GET / HTTP/1.1\r\n"
14456 "Host: www.example.com\r\n"
14457 "Connection: keep-alive\r\n"
14458 "Authorization: auth_token\r\n\r\n");
14459
14460 const MockRead kServerChallenge(
14461 "HTTP/1.1 401 Unauthorized\r\n"
14462 "WWW-Authenticate: Mock realm=server\r\n"
14463 "Content-Type: text/html; charset=iso-8859-1\r\n"
14464 "Content-Length: 14\r\n\r\n"
14465 "Unauthorized\r\n");
14466 const MockRead kSuccess(
14467 "HTTP/1.1 200 OK\r\n"
14468 "Content-Type: text/html; charset=iso-8859-1\r\n"
14469 "Content-Length: 3\r\n\r\n"
14470 "Yes");
14471
14472 MockWrite writes[] = {
14473 // First round
14474 kGet,
14475 // Second round
14476 kGetAuth,
14477 // Third round
14478 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014479 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014480 kGetAuth,
14481 // Competing request
14482 kGet,
[email protected]c871bce92010-07-15 21:51:1414483 };
14484 MockRead reads[] = {
14485 // First round
14486 kServerChallenge,
14487 // Second round
14488 kServerChallenge,
14489 // Third round
[email protected]eca50e122010-09-11 14:03:3014490 kServerChallenge,
14491 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414492 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014493 // Competing response
14494 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414495 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114496 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714497 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414498
Matt Menkef6edce752019-03-19 17:21:5614499 const ClientSocketPool::GroupId kSocketGroup(
14500 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5914501 PrivacyMode::PRIVACY_MODE_DISABLED);
[email protected]7ef4cbbb2011-02-06 11:19:1014502
14503 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414504 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014505 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414506 if (rv == ERR_IO_PENDING)
14507 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114508 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614509 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214510 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814511 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314512 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114513 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14514 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414515
[email protected]7ef4cbbb2011-02-06 11:19:1014516 // In between rounds, another request comes in for the same domain.
14517 // It should not be able to grab the TCP socket that trans has already
14518 // claimed.
bnc691fda62016-08-12 00:43:1614519 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114520 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014521 rv = trans_compete.Start(&request, callback_compete.callback(),
14522 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014524 // callback_compete.WaitForResult at this point would stall forever,
14525 // since the HttpNetworkTransaction does not release the request back to
14526 // the pool until after authentication completes.
14527
14528 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414529 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614530 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414531 if (rv == ERR_IO_PENDING)
14532 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114533 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614534 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214535 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814536 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314537 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114538 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14539 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414540
[email protected]7ef4cbbb2011-02-06 11:19:1014541 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414542 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614543 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414544 if (rv == ERR_IO_PENDING)
14545 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114546 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614547 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214548 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814549 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314550 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114551 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14552 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014553
[email protected]7ef4cbbb2011-02-06 11:19:1014554 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014555 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614556 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014557 if (rv == ERR_IO_PENDING)
14558 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114559 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614560 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214561 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814562 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314563 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014564
asanka463ca4262016-11-16 02:34:3114565 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14566 // auth handler should transition to a DONE state in concert with the remote
14567 // server. But that's not something we can test here with a mock handler.
14568 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14569 auth_handler->state());
14570
[email protected]7ef4cbbb2011-02-06 11:19:1014571 // Read the body since the fourth round was successful. This will also
14572 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414573 scoped_refptr<IOBufferWithSize> io_buf =
14574 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614575 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014576 if (rv == ERR_IO_PENDING)
14577 rv = callback.WaitForResult();
14578 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614579 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014580 EXPECT_EQ(0, rv);
14581 // There are still 0 idle sockets, since the trans_compete transaction
14582 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314583 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014584
14585 // The competing request can now finish. Wait for the headers and then
14586 // read the body.
14587 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114588 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614589 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014590 if (rv == ERR_IO_PENDING)
14591 rv = callback.WaitForResult();
14592 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614593 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014594 EXPECT_EQ(0, rv);
14595
14596 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314597 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414598}
14599
[email protected]65041fa2010-05-21 06:56:5314600// This tests the case that a request is issued via http instead of spdy after
14601// npn is negotiated.
bncd16676a2016-07-20 16:23:0114602TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314603 HttpRequestInfo request;
14604 request.method = "GET";
bncce36dca22015-04-21 22:11:2314605 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014606 request.traffic_annotation =
14607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314608
14609 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314610 MockWrite(
14611 "GET / HTTP/1.1\r\n"
14612 "Host: www.example.org\r\n"
14613 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314614 };
14615
14616 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214617 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314618 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214619 MockRead("\r\n"),
14620 MockRead("hello world"),
14621 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314622 };
14623
[email protected]8ddf8322012-02-23 18:08:0614624 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614625 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314626
[email protected]bb88e1d32013-05-03 23:11:0714627 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314628
Ryan Sleevib8d7ea02018-05-07 20:01:0114629 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714630 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314631
[email protected]49639fa2011-12-20 23:22:4114632 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314633
danakj1fd259a02016-04-16 03:17:0914634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314636
tfarina42834112016-09-22 13:38:2014637 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314638
robpercival214763f2016-07-01 23:27:0114639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14640 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314641
bnc691fda62016-08-12 00:43:1614642 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214643 ASSERT_TRUE(response);
14644 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314645 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14646
14647 std::string response_data;
bnc691fda62016-08-12 00:43:1614648 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314649 EXPECT_EQ("hello world", response_data);
14650
14651 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214652 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314653}
[email protected]26ef6582010-06-24 02:30:4714654
bnc55ff9da2015-08-19 18:42:3514655// Simulate the SSL handshake completing with an NPN negotiation followed by an
14656// immediate server closing of the socket.
14657// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114658TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714659 HttpRequestInfo request;
14660 request.method = "GET";
bncce36dca22015-04-21 22:11:2314661 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014662 request.traffic_annotation =
14663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714664
[email protected]8ddf8322012-02-23 18:08:0614665 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614666 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714667 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714668
Ryan Hamilton0239aac2018-05-19 00:03:1314669 spdy::SpdySerializedFrame req(
14670 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114671 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714672
14673 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614674 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714675 };
14676
Ryan Sleevib8d7ea02018-05-07 20:01:0114677 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714678 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714679
[email protected]49639fa2011-12-20 23:22:4114680 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714681
danakj1fd259a02016-04-16 03:17:0914682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614683 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714684
tfarina42834112016-09-22 13:38:2014685 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114686 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14687 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714688}
[email protected]65d34382010-07-01 18:12:2614689
[email protected]795cbf82013-07-22 09:37:2714690// A subclass of HttpAuthHandlerMock that records the request URL when
14691// it gets it. This is needed since the auth handler may get destroyed
14692// before we get a chance to query it.
14693class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14694 public:
14695 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14696
Chris Watkins7a41d3552017-12-01 02:13:2714697 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714698
14699 protected:
dchengb03027d2014-10-21 12:00:2014700 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14701 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914702 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014703 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714704 *url_ = request->url;
14705 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914706 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714707 }
14708
14709 private:
14710 GURL* url_;
14711};
14712
[email protected]8e6441ca2010-08-19 05:56:3814713// Test that if we cancel the transaction as the connection is completing, that
14714// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114715TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814716 // Setup everything about the connection to complete synchronously, so that
14717 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14718 // for is the callback from the HttpStreamRequest.
14719 // Then cancel the transaction.
14720 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614721 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814722 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614723 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14724 MockRead(SYNCHRONOUS, "hello world"),
14725 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814726 };
14727
[email protected]8e6441ca2010-08-19 05:56:3814728 HttpRequestInfo request;
14729 request.method = "GET";
bncce36dca22015-04-21 22:11:2314730 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014731 request.traffic_annotation =
14732 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814733
danakj1fd259a02016-04-16 03:17:0914734 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814735 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914736 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714737
Ryan Sleevib8d7ea02018-05-07 20:01:0114738 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814739 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714740 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814741
[email protected]49639fa2011-12-20 23:22:4114742 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814743
vishal.b62985ca92015-04-17 08:45:5114744 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114745 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114746 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814747 trans.reset(); // Cancel the transaction here.
14748
fdoray92e35a72016-06-10 15:54:5514749 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014750}
14751
[email protected]ecab6e052014-05-16 14:58:1214752// Test that if a transaction is cancelled after receiving the headers, the
14753// stream is drained properly and added back to the socket pool. The main
14754// purpose of this test is to make sure that an HttpStreamParser can be read
14755// from after the HttpNetworkTransaction and the objects it owns have been
14756// deleted.
14757// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114758TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214759 MockRead data_reads[] = {
14760 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14761 MockRead(ASYNC, "Content-Length: 2\r\n"),
14762 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14763 MockRead(ASYNC, "1"),
14764 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14765 // HttpNetworkTransaction has been deleted.
14766 MockRead(ASYNC, "2"),
14767 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14768 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114769 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214770 session_deps_.socket_factory->AddSocketDataProvider(&data);
14771
danakj1fd259a02016-04-16 03:17:0914772 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214773
14774 {
14775 HttpRequestInfo request;
14776 request.method = "GET";
bncce36dca22015-04-21 22:11:2314777 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014778 request.traffic_annotation =
14779 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214780
dcheng48459ac22014-08-26 00:46:4114781 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214782 TestCompletionCallback callback;
14783
tfarina42834112016-09-22 13:38:2014784 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214786 callback.WaitForResult();
14787
14788 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214789 ASSERT_TRUE(response);
14790 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214791 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14792
14793 // The transaction and HttpRequestInfo are deleted.
14794 }
14795
14796 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5514797 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1214798
14799 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4114800 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1214801}
14802
[email protected]76a505b2010-08-25 06:23:0014803// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0114804TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914805 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914806 ProxyResolutionService::CreateFixedFromPacResult(
14807 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114808 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714809 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014811
[email protected]76a505b2010-08-25 06:23:0014812 HttpRequestInfo request;
14813 request.method = "GET";
bncce36dca22015-04-21 22:11:2314814 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014815 request.traffic_annotation =
14816 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014817
14818 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2314819 MockWrite(
14820 "GET http://www.example.org/ HTTP/1.1\r\n"
14821 "Host: www.example.org\r\n"
14822 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014823 };
14824
14825 MockRead data_reads1[] = {
14826 MockRead("HTTP/1.1 200 OK\r\n"),
14827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14828 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614829 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014830 };
14831
Ryan Sleevib8d7ea02018-05-07 20:01:0114832 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714833 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0014834
[email protected]49639fa2011-12-20 23:22:4114835 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014836
bnc691fda62016-08-12 00:43:1614837 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914838 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614839 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914840 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14841 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014842
bnc691fda62016-08-12 00:43:1614843 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114844 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014845
14846 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114847 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0014848
bnc691fda62016-08-12 00:43:1614849 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214850 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014851
14852 EXPECT_TRUE(response->headers->IsKeepAlive());
14853 EXPECT_EQ(200, response->headers->response_code());
14854 EXPECT_EQ(100, response->headers->GetContentLength());
14855 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714856 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14857 HostPortPair::FromString("myproxy:70")),
14858 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914859 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14860 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14861 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0014862 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2014863
14864 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614865 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014866 TestLoadTimingNotReusedWithPac(load_timing_info,
14867 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0014868}
14869
14870// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0114871TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914872 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914873 ProxyResolutionService::CreateFixedFromPacResult(
14874 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114875 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714876 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914877 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014878
[email protected]76a505b2010-08-25 06:23:0014879 HttpRequestInfo request;
14880 request.method = "GET";
bncce36dca22015-04-21 22:11:2314881 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014882 request.traffic_annotation =
14883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014884
14885 // Since we have proxy, should try to establish tunnel.
14886 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714887 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14888 "Host: www.example.org:443\r\n"
14889 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014890
rsleevidb16bb02015-11-12 23:47:1714891 MockWrite("GET / HTTP/1.1\r\n"
14892 "Host: www.example.org\r\n"
14893 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014894 };
14895
14896 MockRead data_reads1[] = {
14897 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14898
14899 MockRead("HTTP/1.1 200 OK\r\n"),
14900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14901 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614902 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014903 };
14904
Ryan Sleevib8d7ea02018-05-07 20:01:0114905 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714906 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614907 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014909
[email protected]49639fa2011-12-20 23:22:4114910 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014911
bnc691fda62016-08-12 00:43:1614912 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914913 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614914 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914915 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14916 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014917
bnc691fda62016-08-12 00:43:1614918 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014920
14921 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114922 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5414923 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0014924 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014925 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14926 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014927 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014928 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014929 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14930 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014931
bnc691fda62016-08-12 00:43:1614932 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214933 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014934
14935 EXPECT_TRUE(response->headers->IsKeepAlive());
14936 EXPECT_EQ(200, response->headers->response_code());
14937 EXPECT_EQ(100, response->headers->GetContentLength());
14938 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14939 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714940 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14941 HostPortPair::FromString("myproxy:70")),
14942 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914943 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14944 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14945 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2014946
14947 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614948 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014949 TestLoadTimingNotReusedWithPac(load_timing_info,
14950 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0014951}
14952
rsleevidb16bb02015-11-12 23:47:1714953// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
14954// literal host.
bncd16676a2016-07-20 16:23:0114955TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5914956 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914957 ProxyResolutionService::CreateFixedFromPacResult(
14958 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714959 BoundTestNetLog log;
14960 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914961 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1714962
14963 HttpRequestInfo request;
14964 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1514965 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1014966 request.traffic_annotation =
14967 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714968
14969 // Since we have proxy, should try to establish tunnel.
14970 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1514971 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
14972 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1714973 "Proxy-Connection: keep-alive\r\n\r\n"),
14974
14975 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1514976 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1714977 "Connection: keep-alive\r\n\r\n"),
14978 };
14979
14980 MockRead data_reads1[] = {
14981 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14982
14983 MockRead("HTTP/1.1 200 OK\r\n"),
14984 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14985 MockRead("Content-Length: 100\r\n\r\n"),
14986 MockRead(SYNCHRONOUS, OK),
14987 };
14988
Ryan Sleevib8d7ea02018-05-07 20:01:0114989 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1714990 session_deps_.socket_factory->AddSocketDataProvider(&data1);
14991 SSLSocketDataProvider ssl(ASYNC, OK);
14992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14993
14994 TestCompletionCallback callback1;
14995
bnc691fda62016-08-12 00:43:1614996 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1714997
bnc691fda62016-08-12 00:43:1614998 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114999 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715000
15001 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115002 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415003 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715004 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015005 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15006 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715007 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015008 entries, pos,
15009 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15010 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715011
bnc691fda62016-08-12 00:43:1615012 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215013 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715014
15015 EXPECT_TRUE(response->headers->IsKeepAlive());
15016 EXPECT_EQ(200, response->headers->response_code());
15017 EXPECT_EQ(100, response->headers->GetContentLength());
15018 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15019 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715020 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15021 HostPortPair::FromString("myproxy:70")),
15022 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715023
15024 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615025 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715026 TestLoadTimingNotReusedWithPac(load_timing_info,
15027 CONNECT_TIMING_HAS_SSL_TIMES);
15028}
15029
[email protected]76a505b2010-08-25 06:23:0015030// Test a basic HTTPS GET request through a proxy, but the server hangs up
15031// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115032TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915033 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15034 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115035 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715036 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915037 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015038
[email protected]76a505b2010-08-25 06:23:0015039 HttpRequestInfo request;
15040 request.method = "GET";
bncce36dca22015-04-21 22:11:2315041 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015042 request.traffic_annotation =
15043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015044
15045 // Since we have proxy, should try to establish tunnel.
15046 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715047 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15048 "Host: www.example.org:443\r\n"
15049 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015050
rsleevidb16bb02015-11-12 23:47:1715051 MockWrite("GET / HTTP/1.1\r\n"
15052 "Host: www.example.org\r\n"
15053 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015054 };
15055
15056 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015057 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615058 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015059 };
15060
Ryan Sleevib8d7ea02018-05-07 20:01:0115061 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715062 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615063 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015065
[email protected]49639fa2011-12-20 23:22:4115066 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015067
bnc691fda62016-08-12 00:43:1615068 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015069
bnc691fda62016-08-12 00:43:1615070 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115071 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015072
15073 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115074 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415075 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015076 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015077 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15078 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015079 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015080 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015081 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15082 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015083}
15084
[email protected]749eefa82010-09-13 22:14:0315085// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115086TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315087 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915088 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115089 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315090
Raul Tambre94493c652019-03-11 17:18:3515091 spdy::SpdySerializedFrame resp(
15092 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315093 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315094 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115095 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315096 };
15097
Ryan Sleevib8d7ea02018-05-07 20:01:0115098 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715099 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315100
[email protected]8ddf8322012-02-23 18:08:0615101 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615102 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715103 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315104
danakj1fd259a02016-04-16 03:17:0915105 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315106
15107 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315108 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015109 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115110 PRIVACY_MODE_DISABLED,
15111 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2715112 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215113 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315114
15115 HttpRequestInfo request;
15116 request.method = "GET";
bncce36dca22015-04-21 22:11:2315117 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015118 request.traffic_annotation =
15119 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315120
bnc691fda62016-08-12 00:43:1615121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315122
[email protected]41d64e82013-07-03 22:44:2615123 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015124 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115125 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15126 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315127}
15128
[email protected]73b8dd222010-11-11 19:55:2415129// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615130// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215131void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715132 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915133 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715134 request_info.url = GURL("https://www.example.com/");
15135 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915136 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015137 request_info.traffic_annotation =
15138 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715139
[email protected]8ddf8322012-02-23 18:08:0615140 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915141 MockWrite data_writes[] = {
15142 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415143 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115144 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715145 session_deps_.socket_factory->AddSocketDataProvider(&data);
15146 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415147
danakj1fd259a02016-04-16 03:17:0915148 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615149 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415150
[email protected]49639fa2011-12-20 23:22:4115151 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015152 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915153 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415154 rv = callback.WaitForResult();
15155 ASSERT_EQ(error, rv);
15156}
15157
bncd16676a2016-07-20 16:23:0115158TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415159 // Just check a grab bag of cert errors.
15160 static const int kErrors[] = {
15161 ERR_CERT_COMMON_NAME_INVALID,
15162 ERR_CERT_AUTHORITY_INVALID,
15163 ERR_CERT_DATE_INVALID,
15164 };
Avi Drissman4365a4782018-12-28 19:26:2415165 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615166 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15167 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415168 }
15169}
15170
[email protected]bd0b6772011-01-11 19:59:3015171// Ensure that a client certificate is removed from the SSL client auth
15172// cache when:
15173// 1) No proxy is involved.
15174// 2) TLS False Start is disabled.
15175// 3) The initial TLS handshake requests a client certificate.
15176// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115177TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915178 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715179 request_info.url = GURL("https://www.example.com/");
15180 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915181 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015182 request_info.traffic_annotation =
15183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715184
David Benjamin1c4b6d012019-07-08 17:12:5715185 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115186 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015187
15188 // [ssl_]data1 contains the data for the first SSL handshake. When a
15189 // CertificateRequest is received for the first time, the handshake will
15190 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915191 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015192 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715193 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115194 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715195 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015196
15197 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15198 // False Start is not being used, the result of the SSL handshake will be
15199 // returned as part of the SSLClientSocket::Connect() call. This test
15200 // matches the result of a server sending a handshake_failure alert,
15201 // rather than a Finished message, because it requires a client
15202 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915203 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015204 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715205 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115206 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715207 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015208
15209 // [ssl_]data3 contains the data for the third SSL handshake. When a
15210 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315211 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15212 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015213 // of the HttpNetworkTransaction. Because this test failure is due to
15214 // requiring a client certificate, this fallback handshake should also
15215 // fail.
ttuttle859dc7a2015-04-23 19:42:2915216 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315217 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015218 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115220 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715221 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015222
[email protected]80c75f682012-05-26 16:22:1715223 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15224 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215225 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15226 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715227 // of the HttpNetworkTransaction. Because this test failure is due to
15228 // requiring a client certificate, this fallback handshake should also
15229 // fail.
ttuttle859dc7a2015-04-23 19:42:2915230 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715231 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115233 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715234 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715235
danakj1fd259a02016-04-16 03:17:0915236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615237 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015238
[email protected]bd0b6772011-01-11 19:59:3015239 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115240 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015241 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115242 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015243
15244 // Complete the SSL handshake, which should abort due to requiring a
15245 // client certificate.
15246 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115247 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015248
15249 // Indicate that no certificate should be supplied. From the perspective
15250 // of SSLClientCertCache, NULL is just as meaningful as a real
15251 // certificate, so this is the same as supply a
15252 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515253 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115254 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015255
15256 // Ensure the certificate was added to the client auth cache before
15257 // allowing the connection to continue restarting.
15258 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415259 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115260 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415261 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215262 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015263
15264 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715265 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15266 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015267 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115268 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015269
15270 // Ensure that the client certificate is removed from the cache on a
15271 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115272 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415273 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015274}
15275
15276// Ensure that a client certificate is removed from the SSL client auth
15277// cache when:
15278// 1) No proxy is involved.
15279// 2) TLS False Start is enabled.
15280// 3) The initial TLS handshake requests a client certificate.
15281// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115282TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915283 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715284 request_info.url = GURL("https://www.example.com/");
15285 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915286 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015287 request_info.traffic_annotation =
15288 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715289
David Benjamin1c4b6d012019-07-08 17:12:5715290 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115291 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015292
15293 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15294 // return successfully after reading up to the peer's Certificate message.
15295 // This is to allow the caller to call SSLClientSocket::Write(), which can
15296 // enqueue application data to be sent in the same packet as the
15297 // ChangeCipherSpec and Finished messages.
15298 // The actual handshake will be finished when SSLClientSocket::Read() is
15299 // called, which expects to process the peer's ChangeCipherSpec and
15300 // Finished messages. If there was an error negotiating with the peer,
15301 // such as due to the peer requiring a client certificate when none was
15302 // supplied, the alert sent by the peer won't be processed until Read() is
15303 // called.
15304
15305 // Like the non-False Start case, when a client certificate is requested by
15306 // the peer, the handshake is aborted during the Connect() call.
15307 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915308 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015309 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115311 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715312 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015313
15314 // When a client certificate is supplied, Connect() will not be aborted
15315 // when the peer requests the certificate. Instead, the handshake will
15316 // artificially succeed, allowing the caller to write the HTTP request to
15317 // the socket. The handshake messages are not processed until Read() is
15318 // called, which then detects that the handshake was aborted, due to the
15319 // peer sending a handshake_failure because it requires a client
15320 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915321 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015322 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715323 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915324 MockRead data2_reads[] = {
15325 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015326 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115327 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715328 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015329
15330 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715331 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15332 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915333 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015334 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115336 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715337 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015338
[email protected]80c75f682012-05-26 16:22:1715339 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15340 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915341 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715342 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115344 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715345 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715346
[email protected]7799de12013-05-30 05:52:5115347 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915348 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115349 ssl_data5.cert_request_info = cert_request.get();
15350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115351 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115352 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15353
danakj1fd259a02016-04-16 03:17:0915354 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015356
[email protected]bd0b6772011-01-11 19:59:3015357 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115358 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015359 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115360 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015361
15362 // Complete the SSL handshake, which should abort due to requiring a
15363 // client certificate.
15364 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115365 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015366
15367 // Indicate that no certificate should be supplied. From the perspective
15368 // of SSLClientCertCache, NULL is just as meaningful as a real
15369 // certificate, so this is the same as supply a
15370 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515371 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115372 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015373
15374 // Ensure the certificate was added to the client auth cache before
15375 // allowing the connection to continue restarting.
15376 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415377 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115378 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415379 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215380 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015381
[email protected]bd0b6772011-01-11 19:59:3015382 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715383 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15384 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015385 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115386 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015387
15388 // Ensure that the client certificate is removed from the cache on a
15389 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115390 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415391 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015392}
15393
[email protected]8c405132011-01-11 22:03:1815394// Ensure that a client certificate is removed from the SSL client auth
15395// cache when:
15396// 1) An HTTPS proxy is involved.
15397// 3) The HTTPS proxy requests a client certificate.
15398// 4) The client supplies an invalid/unacceptable certificate for the
15399// proxy.
bncd16676a2016-07-20 16:23:0115400TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915401 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15402 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115403 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715404 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815405
David Benjamin3b94b0f2019-04-25 23:07:5215406 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115407 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815408
David Benjamin3b94b0f2019-04-25 23:07:5215409 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15410 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915411 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815412 requests[0].url = GURL("https://www.example.com/");
15413 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915414 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015415 requests[0].traffic_annotation =
15416 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815417
David Benjamin3b94b0f2019-04-25 23:07:5215418 // HTTPS requests are tunneled.
15419 MockWrite https_writes[] = {
15420 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15421 "Host: www.example.com:443\r\n"
15422 "Proxy-Connection: keep-alive\r\n\r\n"),
15423 };
15424
[email protected]8c405132011-01-11 22:03:1815425 requests[1].url = GURL("http://www.example.com/");
15426 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915427 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015428 requests[1].traffic_annotation =
15429 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815430
David Benjamin3b94b0f2019-04-25 23:07:5215431 // HTTP requests are not.
15432 MockWrite http_writes[] = {
15433 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15434 "Host: www.example.com\r\n"
15435 "Proxy-Connection: keep-alive\r\n\r\n"),
15436 };
[email protected]8c405132011-01-11 22:03:1815437
David Benjamin3b94b0f2019-04-25 23:07:5215438 // When the server rejects the client certificate, it will close the
15439 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15440 // TLS 1.2 with False Start), the error is returned out of the first Read().
15441 for (bool reject_in_connect : {true, false}) {
15442 SCOPED_TRACE(reject_in_connect);
15443 // Client certificate errors are typically signaled with
15444 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15445 // protocol error.
15446 for (Error reject_error :
15447 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15448 SCOPED_TRACE(reject_error);
15449 // Tunneled and non-tunneled requests are handled differently. Test both.
15450 for (const HttpRequestInfo& request : requests) {
15451 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815452
David Benjamin3b94b0f2019-04-25 23:07:5215453 session_deps_.socket_factory =
15454 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815455
David Benjamin3b94b0f2019-04-25 23:07:5215456 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15457 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15458 // for proxies. Rather than represending the endpoint
15459 // (www.example.com:443), they represent failures with the HTTPS proxy
15460 // (proxy:70).
15461 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15462 ssl_data1.cert_request_info = cert_request.get();
15463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15464 StaticSocketDataProvider data1;
15465 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815466
David Benjamin3b94b0f2019-04-25 23:07:5215467 base::Optional<SSLSocketDataProvider> ssl_data2;
15468 base::Optional<StaticSocketDataProvider> data2;
15469 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15470 if (reject_in_connect) {
15471 ssl_data2.emplace(ASYNC, reject_error);
15472 // There are no reads or writes.
15473 data2.emplace();
15474 } else {
15475 ssl_data2.emplace(ASYNC, OK);
15476 // We will get one Write() in before observing the error in Read().
15477 if (request.url.SchemeIsCryptographic()) {
15478 data2.emplace(error_in_read, https_writes);
15479 } else {
15480 data2.emplace(error_in_read, http_writes);
15481 }
15482 }
15483 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815484
David Benjamin3b94b0f2019-04-25 23:07:5215485 session_deps_.socket_factory->AddSSLSocketDataProvider(
15486 &ssl_data2.value());
15487 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815488
David Benjamin3b94b0f2019-04-25 23:07:5215489 std::unique_ptr<HttpNetworkSession> session =
15490 CreateSession(&session_deps_);
15491 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15492
15493 // Begin the SSL handshake with the proxy.
15494 TestCompletionCallback callback;
15495 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15496 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15497
15498 // Complete the SSL handshake, which should abort due to requiring a
15499 // client certificate.
15500 rv = callback.WaitForResult();
15501 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15502
15503 // Indicate that no certificate should be supplied. From the
15504 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15505 // real certificate, so this is the same as supply a
15506 // legitimate-but-unacceptable certificate.
15507 rv =
15508 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15509 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15510
15511 // Ensure the certificate was added to the client auth cache before
15512 // allowing the connection to continue restarting.
15513 scoped_refptr<X509Certificate> client_cert;
15514 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115515 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215516 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15517 ASSERT_FALSE(client_cert);
15518 // Ensure the certificate was NOT cached for the endpoint. This only
15519 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4115520 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215521 HostPortPair("www.example.com", 443), &client_cert,
15522 &client_private_key));
15523
15524 // Restart the handshake. This will consume ssl_data2. The result code
15525 // is checked against what ssl_data2 should return.
15526 rv = callback.WaitForResult();
15527 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15528 IsError(reject_error)));
15529
15530 // Now that the new handshake has failed, ensure that the client
15531 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4115532 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215533 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4115534 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215535 HostPortPair("www.example.com", 443), &client_cert,
15536 &client_private_key));
15537 }
15538 }
[email protected]8c405132011-01-11 22:03:1815539 }
15540}
15541
David Benjamin1a0566082019-04-30 07:36:1915542// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15543// requests during a TLS renegotiation.
15544TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15545 HttpRequestInfo request_info;
15546 request_info.url = GURL("https://www.example.com/");
15547 request_info.method = "GET";
15548 request_info.load_flags = LOAD_NORMAL;
15549 request_info.traffic_annotation =
15550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15551
15552 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15553 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15554
15555 std::unique_ptr<FakeClientCertIdentity> identity =
15556 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15557 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15558 ASSERT_TRUE(identity);
15559
15560 // The first connection's handshake succeeds, but we get
15561 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15562 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15563 ssl_data1.cert_request_info = cert_request.get();
15564 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15565 MockWrite data1_writes[] = {
15566 MockWrite("GET / HTTP/1.1\r\n"
15567 "Host: www.example.com\r\n"
15568 "Connection: keep-alive\r\n\r\n"),
15569 };
15570 MockRead data1_reads[] = {
15571 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15572 };
15573 StaticSocketDataProvider data1(data1_reads, data1_writes);
15574 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15575
15576 // After supplying with certificate, we restart the request from the top,
15577 // which succeeds this time.
15578 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15579 ssl_data2.expected_send_client_cert = true;
15580 ssl_data2.expected_client_cert = identity->certificate();
15581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15582 MockWrite data2_writes[] = {
15583 MockWrite("GET / HTTP/1.1\r\n"
15584 "Host: www.example.com\r\n"
15585 "Connection: keep-alive\r\n\r\n"),
15586 };
15587 MockRead data2_reads[] = {
15588 MockRead("HTTP/1.1 200 OK\r\n"
15589 "Content-Length: 0\r\n\r\n"),
15590 };
15591 StaticSocketDataProvider data2(data2_reads, data2_writes);
15592 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15593
15594 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15595 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15596
15597 TestCompletionCallback callback;
15598 int rv = callback.GetResult(
15599 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15600 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15601
15602 rv = trans.RestartWithCertificate(identity->certificate(),
15603 identity->ssl_private_key(),
15604 callback.callback());
15605 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15606
15607 // Ensure the certificate was added to the client auth cache
15608 // allowing the connection to continue restarting.
15609 scoped_refptr<X509Certificate> client_cert;
15610 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115611 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915612 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15613 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15614
15615 // Complete the handshake. The request now succeeds.
15616 rv = callback.WaitForResult();
15617 ASSERT_THAT(rv, IsError(OK));
15618 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15619
15620 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4115621 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915622 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15623 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15624}
15625
bncd16676a2016-07-20 16:23:0115626TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615627 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915628 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915629 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615630
bnc032658ba2016-09-26 18:17:1515631 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615632
Ryan Hamilton0239aac2018-05-19 00:03:1315633 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915634 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815635 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315636 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715637 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615638 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115639 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615640 };
Ryan Hamilton0239aac2018-05-19 00:03:1315641 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515642 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315643 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115644 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315645 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515646 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315647 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115648 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615649 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115650 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15651 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315652 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615653 };
15654
eroman36d84e54432016-03-17 03:23:0215655 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215656 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115657 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715658 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615659
[email protected]aa22b242011-11-16 18:58:2915660 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615661 HttpRequestInfo request1;
15662 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315663 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615664 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015665 request1.traffic_annotation =
15666 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015667 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615668
tfarina42834112016-09-22 13:38:2015669 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115670 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15671 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615672
15673 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215674 ASSERT_TRUE(response);
15675 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215676 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615677
15678 std::string response_data;
robpercival214763f2016-07-01 23:27:0115679 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615680 EXPECT_EQ("hello!", response_data);
15681
bnca4d611d2016-09-22 19:55:3715682 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315683 rv = session_deps_.host_resolver->LoadIntoCache(
15684 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115685 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615686
15687 HttpRequestInfo request2;
15688 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715689 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615690 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015691 request2.traffic_annotation =
15692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015693 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615694
tfarina42834112016-09-22 13:38:2015695 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15697 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615698
15699 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215700 ASSERT_TRUE(response);
15701 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215702 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615703 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215704 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115705 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615706 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615707}
15708
bncd16676a2016-07-20 16:23:0115709TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215710 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915711 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915712 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215713
bnc032658ba2016-09-26 18:17:1515714 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215715
Ryan Hamilton0239aac2018-05-19 00:03:1315716 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915717 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815718 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315719 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715720 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215721 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115722 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215723 };
Ryan Hamilton0239aac2018-05-19 00:03:1315724 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515725 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315726 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115727 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315728 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515729 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315730 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115731 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215732 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115733 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15734 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315735 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215736 };
15737
eroman36d84e54432016-03-17 03:23:0215738 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215739 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115740 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715741 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215742
15743 TestCompletionCallback callback;
15744 HttpRequestInfo request1;
15745 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315746 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215747 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015748 request1.traffic_annotation =
15749 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015750 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215751
tfarina42834112016-09-22 13:38:2015752 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15754 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215755
15756 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215757 ASSERT_TRUE(response);
15758 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215759 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215760
15761 std::string response_data;
robpercival214763f2016-07-01 23:27:0115762 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215763 EXPECT_EQ("hello!", response_data);
15764
15765 HttpRequestInfo request2;
15766 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715767 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215768 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015769 request2.traffic_annotation =
15770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015771 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215772
tfarina42834112016-09-22 13:38:2015773 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15775 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215776
15777 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215778 ASSERT_TRUE(response);
15779 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215780 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215781 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215782 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115783 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215784 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215785}
15786
bnc8016c1f2017-03-31 02:11:2915787// Regression test for https://crbug.com/546991.
15788// The server might not be able to serve an IP pooled request, and might send a
15789// 421 Misdirected Request response status to indicate this.
15790// HttpNetworkTransaction should reset the request and retry without IP pooling.
15791TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15792 // Two hosts resolve to the same IP address.
15793 const std::string ip_addr = "1.2.3.4";
15794 IPAddress ip;
15795 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15796 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15797
Jeremy Roman0579ed62017-08-29 15:56:1915798 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2915799 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15800 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15801
15802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15803
15804 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315805 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2915806 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15807 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315808 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2915809 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315810 spdy::SpdySerializedFrame rst(
15811 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2915812 MockWrite writes1[] = {
15813 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15814 CreateMockWrite(rst, 6),
15815 };
15816
15817 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315818 spdy::SpdySerializedFrame resp1(
15819 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15820 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15821 spdy::SpdyHeaderBlock response_headers;
15822 response_headers[spdy::kHttp2StatusHeader] = "421";
15823 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2915824 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
15825 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15826 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15827
15828 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115829 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2915830 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15831
15832 AddSSLSocketData();
15833
15834 // Retry the second request on a second connection.
15835 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315836 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2915837 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15838 MockWrite writes2[] = {
15839 CreateMockWrite(req3, 0),
15840 };
15841
Ryan Hamilton0239aac2018-05-19 00:03:1315842 spdy::SpdySerializedFrame resp3(
15843 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
15844 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2915845 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15846 MockRead(ASYNC, 0, 3)};
15847
15848 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115849 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2915850 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15851
15852 AddSSLSocketData();
15853
15854 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315855 int rv = session_deps_.host_resolver->LoadIntoCache(
15856 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2915857 EXPECT_THAT(rv, IsOk());
15858
15859 HttpRequestInfo request1;
15860 request1.method = "GET";
15861 request1.url = GURL("https://www.example.org/");
15862 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015863 request1.traffic_annotation =
15864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915865 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15866
Eric Orthf4db66a2019-02-19 21:35:3315867 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2915868 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15870 rv = callback.WaitForResult();
15871 EXPECT_THAT(rv, IsOk());
15872
15873 const HttpResponseInfo* response = trans1.GetResponseInfo();
15874 ASSERT_TRUE(response);
15875 ASSERT_TRUE(response->headers);
15876 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15877 EXPECT_TRUE(response->was_fetched_via_spdy);
15878 EXPECT_TRUE(response->was_alpn_negotiated);
15879 std::string response_data;
15880 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15881 EXPECT_EQ("hello!", response_data);
15882
15883 HttpRequestInfo request2;
15884 request2.method = "GET";
15885 request2.url = GURL("https://mail.example.org/");
15886 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015887 request2.traffic_annotation =
15888 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915889 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15890
15891 BoundTestNetLog log;
15892 rv = trans2.Start(&request2, callback.callback(), log.bound());
15893 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15894 rv = callback.WaitForResult();
15895 EXPECT_THAT(rv, IsOk());
15896
15897 response = trans2.GetResponseInfo();
15898 ASSERT_TRUE(response);
15899 ASSERT_TRUE(response->headers);
15900 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15901 EXPECT_TRUE(response->was_fetched_via_spdy);
15902 EXPECT_TRUE(response->was_alpn_negotiated);
15903 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15904 EXPECT_EQ("hello!", response_data);
15905
Eric Roman79cc7552019-07-19 02:17:5415906 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5915907 ExpectLogContainsSomewhere(
15908 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2915909 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5915910}
15911
15912// Test that HTTP 421 responses are properly returned to the caller if received
15913// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
15914// portions of the response.
15915TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
15916 // Two hosts resolve to the same IP address.
15917 const std::string ip_addr = "1.2.3.4";
15918 IPAddress ip;
15919 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15920 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15921
Jeremy Roman0579ed62017-08-29 15:56:1915922 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5915923 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15924 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15925
15926 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15927
15928 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315929 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5915930 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15931 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315932 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5915933 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315934 spdy::SpdySerializedFrame rst(
15935 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5915936 MockWrite writes1[] = {
15937 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15938 CreateMockWrite(rst, 6),
15939 };
15940
15941 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315942 spdy::SpdySerializedFrame resp1(
15943 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15944 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15945 spdy::SpdyHeaderBlock response_headers;
15946 response_headers[spdy::kHttp2StatusHeader] = "421";
15947 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5915948 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
15949 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15950 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15951
15952 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115953 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5915954 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15955
15956 AddSSLSocketData();
15957
15958 // Retry the second request on a second connection. It returns 421 Misdirected
15959 // Retry again.
15960 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315961 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5915962 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15963 MockWrite writes2[] = {
15964 CreateMockWrite(req3, 0),
15965 };
15966
Ryan Hamilton0239aac2018-05-19 00:03:1315967 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5915968 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1315969 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5915970 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15971 MockRead(ASYNC, 0, 3)};
15972
15973 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115974 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5915975 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15976
15977 AddSSLSocketData();
15978
15979 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315980 int rv = session_deps_.host_resolver->LoadIntoCache(
15981 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5915982 EXPECT_THAT(rv, IsOk());
15983
15984 HttpRequestInfo request1;
15985 request1.method = "GET";
15986 request1.url = GURL("https://www.example.org/");
15987 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015988 request1.traffic_annotation =
15989 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915990 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15991
Eric Orthf4db66a2019-02-19 21:35:3315992 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5915993 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15994 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15995 rv = callback.WaitForResult();
15996 EXPECT_THAT(rv, IsOk());
15997
15998 const HttpResponseInfo* response = trans1.GetResponseInfo();
15999 ASSERT_TRUE(response);
16000 ASSERT_TRUE(response->headers);
16001 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16002 EXPECT_TRUE(response->was_fetched_via_spdy);
16003 EXPECT_TRUE(response->was_alpn_negotiated);
16004 std::string response_data;
16005 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16006 EXPECT_EQ("hello!", response_data);
16007
16008 HttpRequestInfo request2;
16009 request2.method = "GET";
16010 request2.url = GURL("https://mail.example.org/");
16011 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016012 request2.traffic_annotation =
16013 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916014 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16015
16016 BoundTestNetLog log;
16017 rv = trans2.Start(&request2, callback.callback(), log.bound());
16018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16019 rv = callback.WaitForResult();
16020 EXPECT_THAT(rv, IsOk());
16021
16022 // After a retry, the 421 Misdirected Request is reported back up to the
16023 // caller.
16024 response = trans2.GetResponseInfo();
16025 ASSERT_TRUE(response);
16026 ASSERT_TRUE(response->headers);
16027 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16028 EXPECT_TRUE(response->was_fetched_via_spdy);
16029 EXPECT_TRUE(response->was_alpn_negotiated);
16030 EXPECT_TRUE(response->ssl_info.cert);
16031 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16032 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916033}
16034
bncd16676a2016-07-20 16:23:0116035TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316036 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416037 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16038 session_deps_.host_resolver =
16039 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916040 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616041
bnc032658ba2016-09-26 18:17:1516042 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616043
Ryan Hamilton0239aac2018-05-19 00:03:1316044 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916045 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816046 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316047 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716048 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616049 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116050 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616051 };
Ryan Hamilton0239aac2018-05-19 00:03:1316052 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516053 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316054 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116055 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316056 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516057 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316058 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116059 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616060 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116061 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16062 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316063 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616064 };
16065
eroman36d84e54432016-03-17 03:23:0216066 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216067 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116068 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716069 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616070
[email protected]aa22b242011-11-16 18:58:2916071 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616072 HttpRequestInfo request1;
16073 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316074 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616075 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016076 request1.traffic_annotation =
16077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016078 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616079
tfarina42834112016-09-22 13:38:2016080 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116081 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16082 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616083
16084 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216085 ASSERT_TRUE(response);
16086 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216087 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616088
16089 std::string response_data;
robpercival214763f2016-07-01 23:27:0116090 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616091 EXPECT_EQ("hello!", response_data);
16092
16093 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316094 rv = session_deps_.host_resolver->LoadIntoCache(
16095 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116096 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616097
16098 HttpRequestInfo request2;
16099 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716100 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616101 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016102 request2.traffic_annotation =
16103 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016104 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616105
tfarina42834112016-09-22 13:38:2016106 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116107 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16108 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616109
16110 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216111 ASSERT_TRUE(response);
16112 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216113 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616114 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216115 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116116 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616117 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616118}
16119
bncd16676a2016-07-20 16:23:0116120TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316121 const std::string https_url = "https://www.example.org:8080/";
16122 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416123
16124 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316125 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916126 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416127
16128 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116129 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416130 };
16131
Raul Tambre94493c652019-03-11 17:18:3516132 spdy::SpdySerializedFrame resp1(
16133 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316134 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116135 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916136 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416137
Ryan Sleevib8d7ea02018-05-07 20:01:0116138 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416139 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716140 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416141
16142 // HTTP GET for the HTTP URL
16143 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316144 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416145 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316146 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416147 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416148 };
16149
16150 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316151 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16152 MockRead(ASYNC, 2, "hello"),
16153 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416154 };
16155
Ryan Sleevib8d7ea02018-05-07 20:01:0116156 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416157
[email protected]8450d722012-07-02 19:14:0416158 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616159 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16161 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16162 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416163
danakj1fd259a02016-04-16 03:17:0916164 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416165
16166 // Start the first transaction to set up the SpdySession
16167 HttpRequestInfo request1;
16168 request1.method = "GET";
16169 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416170 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016171 request1.traffic_annotation =
16172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016173 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416174 TestCompletionCallback callback1;
16175 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016176 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516177 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416178
robpercival214763f2016-07-01 23:27:0116179 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416180 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16181
16182 // Now, start the HTTP request
16183 HttpRequestInfo request2;
16184 request2.method = "GET";
16185 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416186 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016187 request2.traffic_annotation =
16188 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016189 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416190 TestCompletionCallback callback2;
16191 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016192 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516193 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416194
robpercival214763f2016-07-01 23:27:0116195 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416196 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16197}
16198
bnc5452e2a2015-05-08 16:27:4216199// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16200// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116201TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516202 url::SchemeHostPort server("https", "www.example.org", 443);
16203 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216204
bnc8bef8da22016-05-30 01:28:2516205 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216206 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616207 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16209
16210 // No data should be read from the alternative, because HTTP/1.1 is
16211 // negotiated.
16212 StaticSocketDataProvider data;
16213 session_deps_.socket_factory->AddSocketDataProvider(&data);
16214
16215 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616216 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216217 // mocked. This way the request relies on the alternate Job.
16218 StaticSocketDataProvider data_refused;
16219 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16220 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16221
zhongyi3d4a55e72016-04-22 20:36:4616222 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916223 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016224 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216225 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116226 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216227 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116228 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716229 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216230
bnc5452e2a2015-05-08 16:27:4216231 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616232 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216233 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516234 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1016235 request.traffic_annotation =
16236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216237 TestCompletionCallback callback;
16238
16239 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216240 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016241 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216242 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216243}
16244
bnc40448a532015-05-11 19:13:1416245// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616246// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416247// succeeds, the request should succeed, even if the latter fails because
16248// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116249TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516250 url::SchemeHostPort server("https", "www.example.org", 443);
16251 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416252
16253 // Negotiate HTTP/1.1 with alternative.
16254 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616255 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416256 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16257
16258 // No data should be read from the alternative, because HTTP/1.1 is
16259 // negotiated.
16260 StaticSocketDataProvider data;
16261 session_deps_.socket_factory->AddSocketDataProvider(&data);
16262
zhongyi3d4a55e72016-04-22 20:36:4616263 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416264 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616265 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416266 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16267
16268 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516269 MockWrite("GET / HTTP/1.1\r\n"
16270 "Host: www.example.org\r\n"
16271 "Connection: keep-alive\r\n\r\n"),
16272 MockWrite("GET /second HTTP/1.1\r\n"
16273 "Host: www.example.org\r\n"
16274 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416275 };
16276
16277 MockRead http_reads[] = {
16278 MockRead("HTTP/1.1 200 OK\r\n"),
16279 MockRead("Content-Type: text/html\r\n"),
16280 MockRead("Content-Length: 6\r\n\r\n"),
16281 MockRead("foobar"),
16282 MockRead("HTTP/1.1 200 OK\r\n"),
16283 MockRead("Content-Type: text/html\r\n"),
16284 MockRead("Content-Length: 7\r\n\r\n"),
16285 MockRead("another"),
16286 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116287 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416288 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16289
zhongyi3d4a55e72016-04-22 20:36:4616290 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916291 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016292 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416293 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116294 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216295 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116296 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716297 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416298
16299 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16300 HttpRequestInfo request1;
16301 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516302 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416303 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016304 request1.traffic_annotation =
16305 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416306 TestCompletionCallback callback1;
16307
tfarina42834112016-09-22 13:38:2016308 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416309 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116310 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416311
16312 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216313 ASSERT_TRUE(response1);
16314 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416315 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16316
16317 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116318 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416319 EXPECT_EQ("foobar", response_data1);
16320
16321 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16322 // for alternative service.
16323 EXPECT_TRUE(
16324 http_server_properties->IsAlternativeServiceBroken(alternative_service));
16325
zhongyi3d4a55e72016-04-22 20:36:4616326 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416327 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616328 // to server.
bnc40448a532015-05-11 19:13:1416329 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16330 HttpRequestInfo request2;
16331 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516332 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416333 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016334 request2.traffic_annotation =
16335 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416336 TestCompletionCallback callback2;
16337
tfarina42834112016-09-22 13:38:2016338 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416339 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116340 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416341
16342 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216343 ASSERT_TRUE(response2);
16344 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416345 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16346
16347 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116348 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416349 EXPECT_EQ("another", response_data2);
16350}
16351
bnc5452e2a2015-05-08 16:27:4216352// Alternative service requires HTTP/2 (or SPDY), but there is already a
16353// HTTP/1.1 socket open to the alternative server. That socket should not be
16354// used.
bncd16676a2016-07-20 16:23:0116355TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616356 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216357 HostPortPair alternative("alternative.example.org", 443);
16358 std::string origin_url = "https://origin.example.org:443";
16359 std::string alternative_url = "https://alternative.example.org:443";
16360
16361 // Negotiate HTTP/1.1 with alternative.example.org.
16362 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616363 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216364 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16365
16366 // HTTP/1.1 data for |request1| and |request2|.
16367 MockWrite http_writes[] = {
16368 MockWrite(
16369 "GET / HTTP/1.1\r\n"
16370 "Host: alternative.example.org\r\n"
16371 "Connection: keep-alive\r\n\r\n"),
16372 MockWrite(
16373 "GET / HTTP/1.1\r\n"
16374 "Host: alternative.example.org\r\n"
16375 "Connection: keep-alive\r\n\r\n"),
16376 };
16377
16378 MockRead http_reads[] = {
16379 MockRead(
16380 "HTTP/1.1 200 OK\r\n"
16381 "Content-Type: text/html; charset=iso-8859-1\r\n"
16382 "Content-Length: 40\r\n\r\n"
16383 "first HTTP/1.1 response from alternative"),
16384 MockRead(
16385 "HTTP/1.1 200 OK\r\n"
16386 "Content-Type: text/html; charset=iso-8859-1\r\n"
16387 "Content-Length: 41\r\n\r\n"
16388 "second HTTP/1.1 response from alternative"),
16389 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116390 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216391 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16392
16393 // This test documents that an alternate Job should not pool to an already
16394 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616395 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216396 StaticSocketDataProvider data_refused;
16397 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16398 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16399
zhongyi3d4a55e72016-04-22 20:36:4616400 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916401 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016402 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216403 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116404 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216405 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116406 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716407 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216408
16409 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216410 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616411 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216412 request1.method = "GET";
16413 request1.url = GURL(alternative_url);
16414 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016415 request1.traffic_annotation =
16416 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216417 TestCompletionCallback callback1;
16418
tfarina42834112016-09-22 13:38:2016419 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116420 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616421 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216422 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216423 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216424 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216425 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216426 EXPECT_FALSE(response1->was_fetched_via_spdy);
16427 std::string response_data1;
bnc691fda62016-08-12 00:43:1616428 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216429 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16430
16431 // Request for origin.example.org, which has an alternative service. This
16432 // will start two Jobs: the alternative looks for connections to pool to,
16433 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616434 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216435 // this request fails.
bnc5452e2a2015-05-08 16:27:4216436 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616437 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216438 request2.method = "GET";
16439 request2.url = GURL(origin_url);
16440 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016441 request2.traffic_annotation =
16442 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216443 TestCompletionCallback callback2;
16444
tfarina42834112016-09-22 13:38:2016445 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116446 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216447
16448 // Another transaction to alternative. This is to test that the HTTP/1.1
16449 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216450 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616451 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216452 request3.method = "GET";
16453 request3.url = GURL(alternative_url);
16454 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016455 request3.traffic_annotation =
16456 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216457 TestCompletionCallback callback3;
16458
tfarina42834112016-09-22 13:38:2016459 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116460 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616461 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216462 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216463 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216464 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216465 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216466 EXPECT_FALSE(response3->was_fetched_via_spdy);
16467 std::string response_data3;
bnc691fda62016-08-12 00:43:1616468 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216469 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16470}
16471
bncd16676a2016-07-20 16:23:0116472TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316473 const std::string https_url = "https://www.example.org:8080/";
16474 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416475
rdsmithebb50aa2015-11-12 03:44:3816476 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116477 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816478
[email protected]8450d722012-07-02 19:14:0416479 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316480 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416481 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16482 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16483 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316484 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916485 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316486 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216487 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916488
16489 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316490 spdy::SpdyHeaderBlock req2_block;
16491 req2_block[spdy::kHttp2MethodHeader] = "GET";
16492 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16493 req2_block[spdy::kHttp2SchemeHeader] = "http";
16494 req2_block[spdy::kHttp2PathHeader] = "/";
16495 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516496 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416497
16498 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116499 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16500 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416501 };
16502
Ryan Hamilton0239aac2018-05-19 00:03:1316503 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516504 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316505 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516506 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316507 spdy::SpdySerializedFrame body1(
16508 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16509 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816510 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316511 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816512 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516513 spdy::SpdySerializedFrame resp2(
16514 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316515 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316516 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116517 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316518 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116519 CreateMockRead(wrapped_resp1, 4),
16520 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316521 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116522 CreateMockRead(resp2, 8),
16523 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316524 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16525 };
[email protected]8450d722012-07-02 19:14:0416526
Ryan Sleevib8d7ea02018-05-07 20:01:0116527 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416528 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716529 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416530
Lily Houghton8c2f97d2018-01-22 05:06:5916531 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916532 ProxyResolutionService::CreateFixedFromPacResult(
16533 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116534 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716535 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416536 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616537 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316538 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416539 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616540 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16542 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416543
danakj1fd259a02016-04-16 03:17:0916544 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416545
16546 // Start the first transaction to set up the SpdySession
16547 HttpRequestInfo request1;
16548 request1.method = "GET";
16549 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416550 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016551 request1.traffic_annotation =
16552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016553 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416554 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016555 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416556
mmenke666a6fea2015-12-19 04:16:3316557 // This pause is a hack to avoid running into https://crbug.com/497228.
16558 data1.RunUntilPaused();
16559 base::RunLoop().RunUntilIdle();
16560 data1.Resume();
robpercival214763f2016-07-01 23:27:0116561 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416562 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16563
[email protected]f6c63db52013-02-02 00:35:2216564 LoadTimingInfo load_timing_info1;
16565 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16566 TestLoadTimingNotReusedWithPac(load_timing_info1,
16567 CONNECT_TIMING_HAS_SSL_TIMES);
16568
mmenke666a6fea2015-12-19 04:16:3316569 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416570 HttpRequestInfo request2;
16571 request2.method = "GET";
16572 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416573 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016574 request2.traffic_annotation =
16575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016576 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416577 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016578 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416579
mmenke666a6fea2015-12-19 04:16:3316580 // This pause is a hack to avoid running into https://crbug.com/497228.
16581 data1.RunUntilPaused();
16582 base::RunLoop().RunUntilIdle();
16583 data1.Resume();
robpercival214763f2016-07-01 23:27:0116584 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316585
[email protected]8450d722012-07-02 19:14:0416586 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216587
16588 LoadTimingInfo load_timing_info2;
16589 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16590 // The established SPDY sessions is considered reused by the HTTP request.
16591 TestLoadTimingReusedWithPac(load_timing_info2);
16592 // HTTP requests over a SPDY session should have a different connection
16593 // socket_log_id than requests over a tunnel.
16594 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416595}
16596
[email protected]2d88e7d2012-07-19 17:55:1716597// Test that in the case where we have a SPDY session to a SPDY proxy
16598// that we do not pool other origins that resolve to the same IP when
16599// the certificate does not match the new origin.
16600// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116601TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316602 const std::string url1 = "http://www.example.org/";
16603 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716604 const std::string ip_addr = "1.2.3.4";
16605
rdsmithebb50aa2015-11-12 03:44:3816606 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116607 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816608
[email protected]2d88e7d2012-07-19 17:55:1716609 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316610 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316611 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316612 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516613 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716614
16615 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116616 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716617 };
16618
Raul Tambre94493c652019-03-11 17:18:3516619 spdy::SpdySerializedFrame resp1(
16620 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316621 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716622 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116623 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16624 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716625 };
16626
Ryan Sleevib8d7ea02018-05-07 20:01:0116627 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216628 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916629 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716630 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16631 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316632 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716633
16634 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316635 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916636 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716637
16638 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116639 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716640 };
16641
Ryan Hamilton0239aac2018-05-19 00:03:1316642 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516643 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316644 spdy::SpdySerializedFrame body2(
16645 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116646 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316647 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716648
Ryan Sleevib8d7ea02018-05-07 20:01:0116649 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716650 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316651 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716652
16653 // Set up a proxy config that sends HTTP requests to a proxy, and
16654 // all others direct.
16655 ProxyConfig proxy_config;
16656 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916657 session_deps_.proxy_resolution_service =
16658 std::make_unique<ProxyResolutionService>(
16659 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16660 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16661 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716662
bncce36dca22015-04-21 22:11:2316663 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616664 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716665 // Load a valid cert. Note, that this does not need to
16666 // be valid for proxy because the MockSSLClientSocket does
16667 // not actually verify it. But SpdySession will use this
16668 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916669 ssl1.ssl_info.cert =
16670 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16671 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16673 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716674
16675 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616676 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316677 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16678 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716679
Jeremy Roman0579ed62017-08-29 15:56:1916680 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316681 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716682 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716683
danakj1fd259a02016-04-16 03:17:0916684 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716685
16686 // Start the first transaction to set up the SpdySession
16687 HttpRequestInfo request1;
16688 request1.method = "GET";
16689 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716690 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016691 request1.traffic_annotation =
16692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016693 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716694 TestCompletionCallback callback1;
16695 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016696 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316697 // This pause is a hack to avoid running into https://crbug.com/497228.
16698 data1.RunUntilPaused();
16699 base::RunLoop().RunUntilIdle();
16700 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716701
robpercival214763f2016-07-01 23:27:0116702 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716703 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16704
16705 // Now, start the HTTP request
16706 HttpRequestInfo request2;
16707 request2.method = "GET";
16708 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716709 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016710 request2.traffic_annotation =
16711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016712 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716713 TestCompletionCallback callback2;
16714 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016715 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516716 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716717
16718 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116719 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716720 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16721}
16722
[email protected]85f97342013-04-17 06:12:2416723// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16724// error) in SPDY session, removes the socket from pool and closes the SPDY
16725// session. Verify that new url's from the same HttpNetworkSession (and a new
16726// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116727TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316728 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416729
16730 MockRead reads1[] = {
16731 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16732 };
16733
Ryan Sleevib8d7ea02018-05-07 20:01:0116734 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416735
Ryan Hamilton0239aac2018-05-19 00:03:1316736 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916737 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416738 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116739 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416740 };
16741
Raul Tambre94493c652019-03-11 17:18:3516742 spdy::SpdySerializedFrame resp2(
16743 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316744 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416745 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116746 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16747 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416748 };
16749
Ryan Sleevib8d7ea02018-05-07 20:01:0116750 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416751
[email protected]85f97342013-04-17 06:12:2416752 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616753 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16755 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416756
16757 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616758 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016759 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16760 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416761
danakj1fd259a02016-04-16 03:17:0916762 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016763 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416764
16765 // Start the first transaction to set up the SpdySession and verify that
16766 // connection was closed.
16767 HttpRequestInfo request1;
16768 request1.method = "GET";
16769 request1.url = GURL(https_url);
16770 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016771 request1.traffic_annotation =
16772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016773 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416774 TestCompletionCallback callback1;
16775 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016776 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116777 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416778
16779 // Now, start the second request and make sure it succeeds.
16780 HttpRequestInfo request2;
16781 request2.method = "GET";
16782 request2.url = GURL(https_url);
16783 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016784 request2.traffic_annotation =
16785 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016786 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416787 TestCompletionCallback callback2;
16788 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016789 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416790
robpercival214763f2016-07-01 23:27:0116791 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416792 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16793}
16794
bncd16676a2016-07-20 16:23:0116795TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0316796 ClientSocketPoolManager::set_max_sockets_per_group(
16797 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16798 ClientSocketPoolManager::set_max_sockets_per_pool(
16799 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16800
16801 // Use two different hosts with different IPs so they don't get pooled.
16802 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
16803 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0916804 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0316805
16806 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616807 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316808 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616809 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316810 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16811 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16812
Ryan Hamilton0239aac2018-05-19 00:03:1316813 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916814 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316815 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116816 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0316817 };
Ryan Hamilton0239aac2018-05-19 00:03:1316818 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516819 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316820 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116821 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316822 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116823 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916824 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316825 };
16826
rdsmithebb50aa2015-11-12 03:44:3816827 // Use a separate test instance for the separate SpdySession that will be
16828 // created.
bncd16676a2016-07-20 16:23:0116829 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0116830 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1216831 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0316832
Ryan Hamilton0239aac2018-05-19 00:03:1316833 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4916834 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316835 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116836 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0316837 };
Ryan Hamilton0239aac2018-05-19 00:03:1316838 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516839 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316840 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116841 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316842 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116843 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916844 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316845 };
16846
Ryan Sleevib8d7ea02018-05-07 20:01:0116847 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1216848 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0316849
16850 MockWrite http_write[] = {
16851 MockWrite("GET / HTTP/1.1\r\n"
16852 "Host: www.a.com\r\n"
16853 "Connection: keep-alive\r\n\r\n"),
16854 };
16855
16856 MockRead http_read[] = {
16857 MockRead("HTTP/1.1 200 OK\r\n"),
16858 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16859 MockRead("Content-Length: 6\r\n\r\n"),
16860 MockRead("hello!"),
16861 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116862 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0316863 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16864
16865 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116866 SpdySessionKey spdy_session_key_a(
16867 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16868 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316869 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616870 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316871
16872 TestCompletionCallback callback;
16873 HttpRequestInfo request1;
16874 request1.method = "GET";
16875 request1.url = GURL("https://www.a.com/");
16876 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016877 request1.traffic_annotation =
16878 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816879 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916880 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316881
tfarina42834112016-09-22 13:38:2016882 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116883 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16884 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316885
16886 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216887 ASSERT_TRUE(response);
16888 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216889 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316890 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216891 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0316892
16893 std::string response_data;
robpercival214763f2016-07-01 23:27:0116894 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316895 EXPECT_EQ("hello!", response_data);
16896 trans.reset();
16897 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616898 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316899
16900 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116901 SpdySessionKey spdy_session_key_b(
16902 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16903 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316904 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616905 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316906 HttpRequestInfo request2;
16907 request2.method = "GET";
16908 request2.url = GURL("https://www.b.com/");
16909 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016910 request2.traffic_annotation =
16911 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816912 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916913 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316914
tfarina42834112016-09-22 13:38:2016915 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16917 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316918
16919 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216920 ASSERT_TRUE(response);
16921 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216922 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316923 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216924 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116925 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316926 EXPECT_EQ("hello!", response_data);
16927 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616928 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316929 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616930 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316931
16932 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1116933 SpdySessionKey spdy_session_key_a1(
16934 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16935 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316936 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616937 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0316938 HttpRequestInfo request3;
16939 request3.method = "GET";
16940 request3.url = GURL("http://www.a.com/");
16941 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016942 request3.traffic_annotation =
16943 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816944 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916945 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316946
tfarina42834112016-09-22 13:38:2016947 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16949 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316950
16951 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216952 ASSERT_TRUE(response);
16953 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0316954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16955 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216956 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116957 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316958 EXPECT_EQ("hello!", response_data);
16959 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616960 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316961 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616962 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316963}
16964
bncd16676a2016-07-20 16:23:0116965TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416966 HttpRequestInfo request;
16967 request.method = "GET";
bncce36dca22015-04-21 22:11:2316968 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016969 request.traffic_annotation =
16970 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416971
danakj1fd259a02016-04-16 03:17:0916972 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616973 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416974
ttuttled9dbc652015-09-29 20:00:5916975 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416976 StaticSocketDataProvider data;
16977 data.set_connect_data(mock_connect);
16978 session_deps_.socket_factory->AddSocketDataProvider(&data);
16979
16980 TestCompletionCallback callback;
16981
tfarina42834112016-09-22 13:38:2016982 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416984
16985 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116986 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416987
[email protected]79e1fd62013-06-20 06:50:0416988 // We don't care whether this succeeds or fails, but it shouldn't crash.
16989 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616990 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716991
16992 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616993 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716994 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116995 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916996
16997 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616998 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916999 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417000}
17001
bncd16676a2016-07-20 16:23:0117002TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417003 HttpRequestInfo request;
17004 request.method = "GET";
bncce36dca22015-04-21 22:11:2317005 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017006 request.traffic_annotation =
17007 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417008
danakj1fd259a02016-04-16 03:17:0917009 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617010 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417011
ttuttled9dbc652015-09-29 20:00:5917012 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417013 StaticSocketDataProvider data;
17014 data.set_connect_data(mock_connect);
17015 session_deps_.socket_factory->AddSocketDataProvider(&data);
17016
17017 TestCompletionCallback callback;
17018
tfarina42834112016-09-22 13:38:2017019 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117020 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417021
17022 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117023 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417024
[email protected]79e1fd62013-06-20 06:50:0417025 // We don't care whether this succeeds or fails, but it shouldn't crash.
17026 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617027 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4717028
17029 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617030 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717031 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117032 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917033
17034 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617035 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917036 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417037}
17038
bncd16676a2016-07-20 16:23:0117039TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417040 HttpRequestInfo request;
17041 request.method = "GET";
bncce36dca22015-04-21 22:11:2317042 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017043 request.traffic_annotation =
17044 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417045
danakj1fd259a02016-04-16 03:17:0917046 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617047 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417048
17049 MockWrite data_writes[] = {
17050 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17051 };
17052 MockRead data_reads[] = {
17053 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17054 };
17055
Ryan Sleevib8d7ea02018-05-07 20:01:0117056 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417057 session_deps_.socket_factory->AddSocketDataProvider(&data);
17058
17059 TestCompletionCallback callback;
17060
tfarina42834112016-09-22 13:38:2017061 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417063
17064 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117065 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417066
[email protected]79e1fd62013-06-20 06:50:0417067 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617068 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417069 EXPECT_TRUE(request_headers.HasHeader("Host"));
17070}
17071
bncd16676a2016-07-20 16:23:0117072TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417073 HttpRequestInfo request;
17074 request.method = "GET";
bncce36dca22015-04-21 22:11:2317075 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017076 request.traffic_annotation =
17077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417078
danakj1fd259a02016-04-16 03:17:0917079 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617080 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417081
17082 MockWrite data_writes[] = {
17083 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17084 };
17085 MockRead data_reads[] = {
17086 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17087 };
17088
Ryan Sleevib8d7ea02018-05-07 20:01:0117089 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417090 session_deps_.socket_factory->AddSocketDataProvider(&data);
17091
17092 TestCompletionCallback callback;
17093
tfarina42834112016-09-22 13:38:2017094 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117095 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417096
17097 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117098 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417099
[email protected]79e1fd62013-06-20 06:50:0417100 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617101 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417102 EXPECT_TRUE(request_headers.HasHeader("Host"));
17103}
17104
bncd16676a2016-07-20 16:23:0117105TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417106 HttpRequestInfo request;
17107 request.method = "GET";
bncce36dca22015-04-21 22:11:2317108 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017109 request.traffic_annotation =
17110 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417111
danakj1fd259a02016-04-16 03:17:0917112 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617113 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417114
17115 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317116 MockWrite(
17117 "GET / HTTP/1.1\r\n"
17118 "Host: www.example.org\r\n"
17119 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417120 };
17121 MockRead data_reads[] = {
17122 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17123 };
17124
Ryan Sleevib8d7ea02018-05-07 20:01:0117125 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417126 session_deps_.socket_factory->AddSocketDataProvider(&data);
17127
17128 TestCompletionCallback callback;
17129
tfarina42834112016-09-22 13:38:2017130 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117131 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417132
17133 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117134 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417135
[email protected]79e1fd62013-06-20 06:50:0417136 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617137 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417138 EXPECT_TRUE(request_headers.HasHeader("Host"));
17139}
17140
bncd16676a2016-07-20 16:23:0117141TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417142 HttpRequestInfo request;
17143 request.method = "GET";
bncce36dca22015-04-21 22:11:2317144 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017145 request.traffic_annotation =
17146 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417147
danakj1fd259a02016-04-16 03:17:0917148 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617149 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417150
17151 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317152 MockWrite(
17153 "GET / HTTP/1.1\r\n"
17154 "Host: www.example.org\r\n"
17155 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417156 };
17157 MockRead data_reads[] = {
17158 MockRead(ASYNC, ERR_CONNECTION_RESET),
17159 };
17160
Ryan Sleevib8d7ea02018-05-07 20:01:0117161 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417162 session_deps_.socket_factory->AddSocketDataProvider(&data);
17163
17164 TestCompletionCallback callback;
17165
tfarina42834112016-09-22 13:38:2017166 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417168
17169 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117170 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417171
[email protected]79e1fd62013-06-20 06:50:0417172 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617173 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417174 EXPECT_TRUE(request_headers.HasHeader("Host"));
17175}
17176
bncd16676a2016-07-20 16:23:0117177TEST_F(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
[email protected]79e1fd62013-06-20 06:50:0417178 HttpRequestInfo request;
17179 request.method = "GET";
bncce36dca22015-04-21 22:11:2317180 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0417181 request.extra_headers.SetHeader("X-Foo", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1017182 request.traffic_annotation =
17183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417184
danakj1fd259a02016-04-16 03:17:0917185 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617186 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417187
17188 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317189 MockWrite(
17190 "GET / HTTP/1.1\r\n"
17191 "Host: www.example.org\r\n"
17192 "Connection: keep-alive\r\n"
17193 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417194 };
17195 MockRead data_reads[] = {
17196 MockRead("HTTP/1.1 200 OK\r\n"
17197 "Content-Length: 5\r\n\r\n"
17198 "hello"),
17199 MockRead(ASYNC, ERR_UNEXPECTED),
17200 };
17201
Ryan Sleevib8d7ea02018-05-07 20:01:0117202 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417203 session_deps_.socket_factory->AddSocketDataProvider(&data);
17204
17205 TestCompletionCallback callback;
17206
tfarina42834112016-09-22 13:38:2017207 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117208 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417209
17210 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117211 EXPECT_THAT(rv, IsOk());
[email protected]79e1fd62013-06-20 06:50:0417212
17213 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617214 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417215 std::string foo;
17216 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
17217 EXPECT_EQ("bar", foo);
17218}
17219
[email protected]043b68c82013-08-22 23:41:5217220// Tests that when a used socket is returned to the SSL socket pool, it's closed
17221// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117222TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217223 ClientSocketPoolManager::set_max_sockets_per_group(
17224 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17225 ClientSocketPoolManager::set_max_sockets_per_pool(
17226 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17227
17228 // Set up SSL request.
17229
17230 HttpRequestInfo ssl_request;
17231 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317232 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017233 ssl_request.traffic_annotation =
17234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217235
17236 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317237 MockWrite(
17238 "GET / HTTP/1.1\r\n"
17239 "Host: www.example.org\r\n"
17240 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217241 };
17242 MockRead ssl_reads[] = {
17243 MockRead("HTTP/1.1 200 OK\r\n"),
17244 MockRead("Content-Length: 11\r\n\r\n"),
17245 MockRead("hello world"),
17246 MockRead(SYNCHRONOUS, OK),
17247 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117248 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217249 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17250
17251 SSLSocketDataProvider ssl(ASYNC, OK);
17252 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17253
17254 // Set up HTTP request.
17255
17256 HttpRequestInfo http_request;
17257 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317258 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017259 http_request.traffic_annotation =
17260 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217261
17262 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317263 MockWrite(
17264 "GET / HTTP/1.1\r\n"
17265 "Host: www.example.org\r\n"
17266 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217267 };
17268 MockRead http_reads[] = {
17269 MockRead("HTTP/1.1 200 OK\r\n"),
17270 MockRead("Content-Length: 7\r\n\r\n"),
17271 MockRead("falafel"),
17272 MockRead(SYNCHRONOUS, OK),
17273 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117274 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217275 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17276
danakj1fd259a02016-04-16 03:17:0917277 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217278
17279 // Start the SSL request.
17280 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617281 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017282 ASSERT_EQ(ERR_IO_PENDING,
17283 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17284 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217285
17286 // Start the HTTP request. Pool should stall.
17287 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617288 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017289 ASSERT_EQ(ERR_IO_PENDING,
17290 http_trans.Start(&http_request, http_callback.callback(),
17291 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117292 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217293
17294 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117295 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217296 std::string response_data;
bnc691fda62016-08-12 00:43:1617297 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217298 EXPECT_EQ("hello world", response_data);
17299
17300 // The SSL socket should automatically be closed, so the HTTP request can
17301 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317302 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117303 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217304
17305 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117306 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617307 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217308 EXPECT_EQ("falafel", response_data);
17309
dcheng48459ac22014-08-26 00:46:4117310 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217311}
17312
17313// Tests that when a SSL connection is established but there's no corresponding
17314// request that needs it, the new socket is closed if the transport socket pool
17315// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117316TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217317 ClientSocketPoolManager::set_max_sockets_per_group(
17318 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17319 ClientSocketPoolManager::set_max_sockets_per_pool(
17320 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17321
17322 // Set up an ssl request.
17323
17324 HttpRequestInfo ssl_request;
17325 ssl_request.method = "GET";
17326 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1017327 ssl_request.traffic_annotation =
17328 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217329
17330 // No data will be sent on the SSL socket.
17331 StaticSocketDataProvider ssl_data;
17332 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17333
17334 SSLSocketDataProvider ssl(ASYNC, OK);
17335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17336
17337 // Set up HTTP request.
17338
17339 HttpRequestInfo http_request;
17340 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317341 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017342 http_request.traffic_annotation =
17343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217344
17345 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317346 MockWrite(
17347 "GET / HTTP/1.1\r\n"
17348 "Host: www.example.org\r\n"
17349 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217350 };
17351 MockRead http_reads[] = {
17352 MockRead("HTTP/1.1 200 OK\r\n"),
17353 MockRead("Content-Length: 7\r\n\r\n"),
17354 MockRead("falafel"),
17355 MockRead(SYNCHRONOUS, OK),
17356 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117357 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217358 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17359
danakj1fd259a02016-04-16 03:17:0917360 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217361
17362 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17363 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917364 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917365 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317366 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217367
17368 // Start the HTTP request. Pool should stall.
17369 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617370 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017371 ASSERT_EQ(ERR_IO_PENDING,
17372 http_trans.Start(&http_request, http_callback.callback(),
17373 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117374 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217375
17376 // The SSL connection will automatically be closed once the connection is
17377 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117378 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217379 std::string response_data;
bnc691fda62016-08-12 00:43:1617380 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217381 EXPECT_EQ("falafel", response_data);
17382
dcheng48459ac22014-08-26 00:46:4117383 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217384}
17385
bncd16676a2016-07-20 16:23:0117386TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917387 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217388 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917389 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217390 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417391
17392 HttpRequestInfo request;
17393 request.method = "POST";
17394 request.url = GURL("http://www.foo.com/");
17395 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017396 request.traffic_annotation =
17397 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417398
danakj1fd259a02016-04-16 03:17:0917399 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617400 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417401 // Send headers successfully, but get an error while sending the body.
17402 MockWrite data_writes[] = {
17403 MockWrite("POST / HTTP/1.1\r\n"
17404 "Host: www.foo.com\r\n"
17405 "Connection: keep-alive\r\n"
17406 "Content-Length: 3\r\n\r\n"),
17407 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17408 };
17409
17410 MockRead data_reads[] = {
17411 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17412 MockRead("hello world"),
17413 MockRead(SYNCHRONOUS, OK),
17414 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117415 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417416 session_deps_.socket_factory->AddSocketDataProvider(&data);
17417
17418 TestCompletionCallback callback;
17419
tfarina42834112016-09-22 13:38:2017420 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117421 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417422
17423 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117424 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417425
bnc691fda62016-08-12 00:43:1617426 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217427 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417428
wezca1070932016-05-26 20:30:5217429 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417430 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17431
17432 std::string response_data;
bnc691fda62016-08-12 00:43:1617433 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117434 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417435 EXPECT_EQ("hello world", response_data);
17436}
17437
17438// This test makes sure the retry logic doesn't trigger when reading an error
17439// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117440TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417441 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917442 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417443 MockWrite data_writes[] = {
17444 MockWrite("GET / HTTP/1.1\r\n"
17445 "Host: www.foo.com\r\n"
17446 "Connection: keep-alive\r\n\r\n"),
17447 MockWrite("POST / HTTP/1.1\r\n"
17448 "Host: www.foo.com\r\n"
17449 "Connection: keep-alive\r\n"
17450 "Content-Length: 3\r\n\r\n"),
17451 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17452 };
17453
17454 MockRead data_reads[] = {
17455 MockRead("HTTP/1.1 200 Peachy\r\n"
17456 "Content-Length: 14\r\n\r\n"),
17457 MockRead("first response"),
17458 MockRead("HTTP/1.1 400 Not OK\r\n"
17459 "Content-Length: 15\r\n\r\n"),
17460 MockRead("second response"),
17461 MockRead(SYNCHRONOUS, OK),
17462 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117463 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417464 session_deps_.socket_factory->AddSocketDataProvider(&data);
17465
17466 TestCompletionCallback callback;
17467 HttpRequestInfo request1;
17468 request1.method = "GET";
17469 request1.url = GURL("http://www.foo.com/");
17470 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017471 request1.traffic_annotation =
17472 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417473
bnc87dcefc2017-05-25 12:47:5817474 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917475 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017476 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417478
17479 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117480 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417481
17482 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217483 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417484
wezca1070932016-05-26 20:30:5217485 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417486 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17487
17488 std::string response_data1;
17489 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117490 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417491 EXPECT_EQ("first response", response_data1);
17492 // Delete the transaction to release the socket back into the socket pool.
17493 trans1.reset();
17494
danakj1fd259a02016-04-16 03:17:0917495 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217496 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917497 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217498 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417499
17500 HttpRequestInfo request2;
17501 request2.method = "POST";
17502 request2.url = GURL("http://www.foo.com/");
17503 request2.upload_data_stream = &upload_data_stream;
17504 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017505 request2.traffic_annotation =
17506 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417507
bnc691fda62016-08-12 00:43:1617508 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017509 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117510 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417511
17512 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117513 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417514
bnc691fda62016-08-12 00:43:1617515 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217516 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417517
wezca1070932016-05-26 20:30:5217518 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417519 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17520
17521 std::string response_data2;
bnc691fda62016-08-12 00:43:1617522 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117523 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417524 EXPECT_EQ("second response", response_data2);
17525}
17526
bncd16676a2016-07-20 16:23:0117527TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417528 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917529 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217530 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917531 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217532 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417533
17534 HttpRequestInfo request;
17535 request.method = "POST";
17536 request.url = GURL("http://www.foo.com/");
17537 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017538 request.traffic_annotation =
17539 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417540
danakj1fd259a02016-04-16 03:17:0917541 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617542 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417543 // Send headers successfully, but get an error while sending the body.
17544 MockWrite data_writes[] = {
17545 MockWrite("POST / HTTP/1.1\r\n"
17546 "Host: www.foo.com\r\n"
17547 "Connection: keep-alive\r\n"
17548 "Content-Length: 3\r\n\r\n"
17549 "fo"),
17550 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17551 };
17552
17553 MockRead data_reads[] = {
17554 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17555 MockRead("hello world"),
17556 MockRead(SYNCHRONOUS, OK),
17557 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117558 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417559 session_deps_.socket_factory->AddSocketDataProvider(&data);
17560
17561 TestCompletionCallback callback;
17562
tfarina42834112016-09-22 13:38:2017563 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117564 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417565
17566 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117567 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417568
bnc691fda62016-08-12 00:43:1617569 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217570 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417571
wezca1070932016-05-26 20:30:5217572 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417573 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17574
17575 std::string response_data;
bnc691fda62016-08-12 00:43:1617576 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117577 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417578 EXPECT_EQ("hello world", response_data);
17579}
17580
17581// This tests the more common case than the previous test, where headers and
17582// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117583TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717584 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417585
17586 HttpRequestInfo request;
17587 request.method = "POST";
17588 request.url = GURL("http://www.foo.com/");
17589 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017590 request.traffic_annotation =
17591 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417592
danakj1fd259a02016-04-16 03:17:0917593 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617594 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417595 // Send headers successfully, but get an error while sending the body.
17596 MockWrite data_writes[] = {
17597 MockWrite("POST / HTTP/1.1\r\n"
17598 "Host: www.foo.com\r\n"
17599 "Connection: keep-alive\r\n"
17600 "Transfer-Encoding: chunked\r\n\r\n"),
17601 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17602 };
17603
17604 MockRead data_reads[] = {
17605 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17606 MockRead("hello world"),
17607 MockRead(SYNCHRONOUS, OK),
17608 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117609 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417610 session_deps_.socket_factory->AddSocketDataProvider(&data);
17611
17612 TestCompletionCallback callback;
17613
tfarina42834112016-09-22 13:38:2017614 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117615 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417616 // Make sure the headers are sent before adding a chunk. This ensures that
17617 // they can't be merged with the body in a single send. Not currently
17618 // necessary since a chunked body is never merged with headers, but this makes
17619 // the test more future proof.
17620 base::RunLoop().RunUntilIdle();
17621
mmenkecbc2b712014-10-09 20:29:0717622 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417623
17624 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117625 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417626
bnc691fda62016-08-12 00:43:1617627 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217628 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417629
wezca1070932016-05-26 20:30:5217630 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417631 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17632
17633 std::string response_data;
bnc691fda62016-08-12 00:43:1617634 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117635 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417636 EXPECT_EQ("hello world", response_data);
17637}
17638
bncd16676a2016-07-20 16:23:0117639TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917640 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217641 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917642 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217643 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417644
17645 HttpRequestInfo request;
17646 request.method = "POST";
17647 request.url = GURL("http://www.foo.com/");
17648 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017649 request.traffic_annotation =
17650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417651
danakj1fd259a02016-04-16 03:17:0917652 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617653 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417654
17655 MockWrite data_writes[] = {
17656 MockWrite("POST / HTTP/1.1\r\n"
17657 "Host: www.foo.com\r\n"
17658 "Connection: keep-alive\r\n"
17659 "Content-Length: 3\r\n\r\n"),
17660 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17661 };
17662
17663 MockRead data_reads[] = {
17664 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17665 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17666 MockRead("hello world"),
17667 MockRead(SYNCHRONOUS, OK),
17668 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117669 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417670 session_deps_.socket_factory->AddSocketDataProvider(&data);
17671
17672 TestCompletionCallback callback;
17673
tfarina42834112016-09-22 13:38:2017674 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417676
17677 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117678 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417679
bnc691fda62016-08-12 00:43:1617680 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217681 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417682
wezca1070932016-05-26 20:30:5217683 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417684 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17685
17686 std::string response_data;
bnc691fda62016-08-12 00:43:1617687 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117688 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417689 EXPECT_EQ("hello world", response_data);
17690}
17691
bncd16676a2016-07-20 16:23:0117692TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917693 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217694 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917695 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217696 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417697
17698 HttpRequestInfo request;
17699 request.method = "POST";
17700 request.url = GURL("http://www.foo.com/");
17701 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017702 request.traffic_annotation =
17703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417704
danakj1fd259a02016-04-16 03:17:0917705 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617706 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417707 // Send headers successfully, but get an error while sending the body.
17708 MockWrite data_writes[] = {
17709 MockWrite("POST / HTTP/1.1\r\n"
17710 "Host: www.foo.com\r\n"
17711 "Connection: keep-alive\r\n"
17712 "Content-Length: 3\r\n\r\n"),
17713 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17714 };
17715
17716 MockRead data_reads[] = {
17717 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17718 MockRead("hello world"),
17719 MockRead(SYNCHRONOUS, OK),
17720 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117721 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417722 session_deps_.socket_factory->AddSocketDataProvider(&data);
17723
17724 TestCompletionCallback callback;
17725
tfarina42834112016-09-22 13:38:2017726 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417728
17729 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117730 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417731}
17732
bncd16676a2016-07-20 16:23:0117733TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417734 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917735 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217736 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917737 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217738 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417739
17740 HttpRequestInfo request;
17741 request.method = "POST";
17742 request.url = GURL("http://www.foo.com/");
17743 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017744 request.traffic_annotation =
17745 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417746
danakj1fd259a02016-04-16 03:17:0917747 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617748 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417749 // Send headers successfully, but get an error while sending the body.
17750 MockWrite data_writes[] = {
17751 MockWrite("POST / HTTP/1.1\r\n"
17752 "Host: www.foo.com\r\n"
17753 "Connection: keep-alive\r\n"
17754 "Content-Length: 3\r\n\r\n"),
17755 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17756 };
17757
17758 MockRead data_reads[] = {
17759 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17760 MockRead("HTTP/1.0 302 Redirect\r\n"),
17761 MockRead("Location: http://somewhere-else.com/\r\n"),
17762 MockRead("Content-Length: 0\r\n\r\n"),
17763 MockRead(SYNCHRONOUS, OK),
17764 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117765 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417766 session_deps_.socket_factory->AddSocketDataProvider(&data);
17767
17768 TestCompletionCallback callback;
17769
tfarina42834112016-09-22 13:38:2017770 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417772
17773 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117774 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417775}
17776
bncd16676a2016-07-20 16:23:0117777TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917778 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217779 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917780 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217781 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417782
17783 HttpRequestInfo request;
17784 request.method = "POST";
17785 request.url = GURL("http://www.foo.com/");
17786 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017787 request.traffic_annotation =
17788 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417789
danakj1fd259a02016-04-16 03:17:0917790 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617791 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417792 // Send headers successfully, but get an error while sending the body.
17793 MockWrite data_writes[] = {
17794 MockWrite("POST / HTTP/1.1\r\n"
17795 "Host: www.foo.com\r\n"
17796 "Connection: keep-alive\r\n"
17797 "Content-Length: 3\r\n\r\n"),
17798 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17799 };
17800
17801 MockRead data_reads[] = {
17802 MockRead("HTTP 0.9 rocks!"),
17803 MockRead(SYNCHRONOUS, OK),
17804 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117805 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417806 session_deps_.socket_factory->AddSocketDataProvider(&data);
17807
17808 TestCompletionCallback callback;
17809
tfarina42834112016-09-22 13:38:2017810 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417812
17813 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117814 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417815}
17816
bncd16676a2016-07-20 16:23:0117817TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917818 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217819 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917820 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217821 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417822
17823 HttpRequestInfo request;
17824 request.method = "POST";
17825 request.url = GURL("http://www.foo.com/");
17826 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017827 request.traffic_annotation =
17828 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417829
danakj1fd259a02016-04-16 03:17:0917830 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617831 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417832 // Send headers successfully, but get an error while sending the body.
17833 MockWrite data_writes[] = {
17834 MockWrite("POST / HTTP/1.1\r\n"
17835 "Host: www.foo.com\r\n"
17836 "Connection: keep-alive\r\n"
17837 "Content-Length: 3\r\n\r\n"),
17838 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17839 };
17840
17841 MockRead data_reads[] = {
17842 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17843 MockRead(SYNCHRONOUS, OK),
17844 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117845 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417846 session_deps_.socket_factory->AddSocketDataProvider(&data);
17847
17848 TestCompletionCallback callback;
17849
tfarina42834112016-09-22 13:38:2017850 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417852
17853 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117854 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417855}
17856
Bence Békydca6bd92018-01-30 13:43:0617857#if BUILDFLAG(ENABLE_WEBSOCKETS)
17858
17859namespace {
17860
17861void AddWebSocketHeaders(HttpRequestHeaders* headers) {
17862 headers->SetHeader("Connection", "Upgrade");
17863 headers->SetHeader("Upgrade", "websocket");
17864 headers->SetHeader("Origin", "http://www.example.org");
17865 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0617866}
17867
17868} // namespace
17869
17870TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0117871 for (bool secure : {true, false}) {
17872 MockWrite data_writes[] = {
17873 MockWrite("GET / HTTP/1.1\r\n"
17874 "Host: www.example.org\r\n"
17875 "Connection: Upgrade\r\n"
17876 "Upgrade: websocket\r\n"
17877 "Origin: http://www.example.org\r\n"
17878 "Sec-WebSocket-Version: 13\r\n"
17879 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17880 "Sec-WebSocket-Extensions: permessage-deflate; "
17881 "client_max_window_bits\r\n\r\n")};
17882
17883 MockRead data_reads[] = {
17884 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17885 "Upgrade: websocket\r\n"
17886 "Connection: Upgrade\r\n"
17887 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
17888
Ryan Sleevib8d7ea02018-05-07 20:01:0117889 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0117890 session_deps_.socket_factory->AddSocketDataProvider(&data);
17891 SSLSocketDataProvider ssl(ASYNC, OK);
17892 if (secure)
17893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0617894
17895 HttpRequestInfo request;
17896 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0117897 request.url =
17898 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
17899 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1017900 request.traffic_annotation =
17901 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0617902
Bence Béky2fcf4fa2018-04-06 20:06:0117903 TestWebSocketHandshakeStreamCreateHelper
17904 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1517905
Bence Béky2fcf4fa2018-04-06 20:06:0117906 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0617907 HttpNetworkTransaction trans(LOW, session.get());
17908 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0117909 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0617910
17911 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0117912 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0617914
Bence Béky2fcf4fa2018-04-06 20:06:0117915 const HttpStreamRequest* stream_request = trans.stream_request_.get();
17916 ASSERT_TRUE(stream_request);
17917 EXPECT_EQ(&websocket_handshake_stream_create_helper,
17918 stream_request->websocket_handshake_stream_create_helper());
17919
17920 rv = callback.WaitForResult();
17921 EXPECT_THAT(rv, IsOk());
17922
17923 EXPECT_TRUE(data.AllReadDataConsumed());
17924 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0617925 }
17926}
17927
Adam Rice425cf122015-01-19 06:18:2417928// Verify that proxy headers are not sent to the destination server when
17929// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0117930TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2417931 HttpRequestInfo request;
17932 request.method = "GET";
bncce36dca22015-04-21 22:11:2317933 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017934 request.traffic_annotation =
17935 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417936 AddWebSocketHeaders(&request.extra_headers);
17937
17938 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917939 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917940 ProxyResolutionService::CreateFixedFromPacResult(
17941 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417942
danakj1fd259a02016-04-16 03:17:0917943 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417944
17945 // Since a proxy is configured, try to establish a tunnel.
17946 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1717947 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17948 "Host: www.example.org:443\r\n"
17949 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417950
17951 // After calling trans->RestartWithAuth(), this is the request we should
17952 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1717953 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17954 "Host: www.example.org:443\r\n"
17955 "Proxy-Connection: keep-alive\r\n"
17956 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417957
rsleevidb16bb02015-11-12 23:47:1717958 MockWrite("GET / HTTP/1.1\r\n"
17959 "Host: www.example.org\r\n"
17960 "Connection: Upgrade\r\n"
17961 "Upgrade: websocket\r\n"
17962 "Origin: http://www.example.org\r\n"
17963 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1517964 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17965 "Sec-WebSocket-Extensions: permessage-deflate; "
17966 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417967
17968 // The proxy responds to the connect with a 407, using a persistent
17969 // connection.
17970 MockRead data_reads[] = {
17971 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1517972 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
17973 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
17974 "Content-Length: 0\r\n"
17975 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417976
17977 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17978
Bence Béky8d1c6052018-02-07 12:48:1517979 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17980 "Upgrade: websocket\r\n"
17981 "Connection: Upgrade\r\n"
17982 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417983
Ryan Sleevib8d7ea02018-05-07 20:01:0117984 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417985 session_deps_.socket_factory->AddSocketDataProvider(&data);
17986 SSLSocketDataProvider ssl(ASYNC, OK);
17987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17988
Bence Béky8d1c6052018-02-07 12:48:1517989 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17990
bnc87dcefc2017-05-25 12:47:5817991 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917992 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417993 trans->SetWebSocketHandshakeStreamCreateHelper(
17994 &websocket_stream_create_helper);
17995
17996 {
17997 TestCompletionCallback callback;
17998
tfarina42834112016-09-22 13:38:2017999 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118000 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418001
18002 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118003 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418004 }
18005
18006 const HttpResponseInfo* response = trans->GetResponseInfo();
18007 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218008 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418009 EXPECT_EQ(407, response->headers->response_code());
18010
18011 {
18012 TestCompletionCallback callback;
18013
18014 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18015 callback.callback());
robpercival214763f2016-07-01 23:27:0118016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418017
18018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118019 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418020 }
18021
18022 response = trans->GetResponseInfo();
18023 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218024 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418025
18026 EXPECT_EQ(101, response->headers->response_code());
18027
18028 trans.reset();
18029 session->CloseAllConnections();
18030}
18031
18032// Verify that proxy headers are not sent to the destination server when
18033// establishing a tunnel for an insecure WebSocket connection.
18034// This requires the authentication info to be injected into the auth cache
18035// due to crbug.com/395064
18036// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118037TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418038 HttpRequestInfo request;
18039 request.method = "GET";
bncce36dca22015-04-21 22:11:2318040 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018041 request.traffic_annotation =
18042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418043 AddWebSocketHeaders(&request.extra_headers);
18044
18045 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918046 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918047 ProxyResolutionService::CreateFixedFromPacResult(
18048 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418049
danakj1fd259a02016-04-16 03:17:0918050 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418051
18052 MockWrite data_writes[] = {
18053 // Try to establish a tunnel for the WebSocket connection, with
18054 // credentials. Because WebSockets have a separate set of socket pools,
18055 // they cannot and will not use the same TCP/IP connection as the
18056 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518057 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18058 "Host: www.example.org:80\r\n"
18059 "Proxy-Connection: keep-alive\r\n"
18060 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418061
Bence Béky8d1c6052018-02-07 12:48:1518062 MockWrite("GET / HTTP/1.1\r\n"
18063 "Host: www.example.org\r\n"
18064 "Connection: Upgrade\r\n"
18065 "Upgrade: websocket\r\n"
18066 "Origin: http://www.example.org\r\n"
18067 "Sec-WebSocket-Version: 13\r\n"
18068 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18069 "Sec-WebSocket-Extensions: permessage-deflate; "
18070 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418071
18072 MockRead data_reads[] = {
18073 // HTTP CONNECT with credentials.
18074 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18075
18076 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518077 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18078 "Upgrade: websocket\r\n"
18079 "Connection: Upgrade\r\n"
18080 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418081
Ryan Sleevib8d7ea02018-05-07 20:01:0118082 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418083 session_deps_.socket_factory->AddSocketDataProvider(&data);
18084
18085 session->http_auth_cache()->Add(
18086 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
18087 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
18088
Bence Béky8d1c6052018-02-07 12:48:1518089 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18090
bnc87dcefc2017-05-25 12:47:5818091 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918092 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418093 trans->SetWebSocketHandshakeStreamCreateHelper(
18094 &websocket_stream_create_helper);
18095
18096 TestCompletionCallback callback;
18097
tfarina42834112016-09-22 13:38:2018098 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118099 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418100
18101 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118102 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418103
18104 const HttpResponseInfo* response = trans->GetResponseInfo();
18105 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218106 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418107
18108 EXPECT_EQ(101, response->headers->response_code());
18109
18110 trans.reset();
18111 session->CloseAllConnections();
18112}
18113
Matt Menke1d6093e32019-03-22 17:33:4318114// WebSockets over QUIC is not supported, including over QUIC proxies.
18115TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18116 for (bool secure : {true, false}) {
18117 SCOPED_TRACE(secure);
18118 session_deps_.proxy_resolution_service =
18119 ProxyResolutionService::CreateFixedFromPacResult(
18120 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18121 session_deps_.enable_quic = true;
18122
18123 HttpRequestInfo request;
18124 request.url =
18125 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18126 AddWebSocketHeaders(&request.extra_headers);
18127 request.traffic_annotation =
18128 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18129
18130 TestWebSocketHandshakeStreamCreateHelper
18131 websocket_handshake_stream_create_helper;
18132
18133 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18134 HttpNetworkTransaction trans(LOW, session.get());
18135 trans.SetWebSocketHandshakeStreamCreateHelper(
18136 &websocket_handshake_stream_create_helper);
18137
18138 TestCompletionCallback callback;
18139 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18140 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18141
18142 rv = callback.WaitForResult();
18143 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18144 }
18145}
18146
Bence Békydca6bd92018-01-30 13:43:0618147#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18148
bncd16676a2016-07-20 16:23:0118149TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918150 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218151 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918152 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218153 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218154
18155 HttpRequestInfo request;
18156 request.method = "POST";
18157 request.url = GURL("http://www.foo.com/");
18158 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018159 request.traffic_annotation =
18160 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218161
danakj1fd259a02016-04-16 03:17:0918162 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618163 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218164 MockWrite data_writes[] = {
18165 MockWrite("POST / HTTP/1.1\r\n"
18166 "Host: www.foo.com\r\n"
18167 "Connection: keep-alive\r\n"
18168 "Content-Length: 3\r\n\r\n"),
18169 MockWrite("foo"),
18170 };
18171
18172 MockRead data_reads[] = {
18173 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18174 MockRead(SYNCHRONOUS, OK),
18175 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118176 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218177 session_deps_.socket_factory->AddSocketDataProvider(&data);
18178
18179 TestCompletionCallback callback;
18180
18181 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018182 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118183 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218184
18185 std::string response_data;
bnc691fda62016-08-12 00:43:1618186 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218187
Ryan Sleevib8d7ea02018-05-07 20:01:0118188 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18189 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218190}
18191
bncd16676a2016-07-20 16:23:0118192TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918193 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218194 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918195 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218196 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218197
18198 HttpRequestInfo request;
18199 request.method = "POST";
18200 request.url = GURL("http://www.foo.com/");
18201 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018202 request.traffic_annotation =
18203 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218204
danakj1fd259a02016-04-16 03:17:0918205 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618206 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218207 MockWrite data_writes[] = {
18208 MockWrite("POST / HTTP/1.1\r\n"
18209 "Host: www.foo.com\r\n"
18210 "Connection: keep-alive\r\n"
18211 "Content-Length: 3\r\n\r\n"),
18212 MockWrite("foo"),
18213 };
18214
18215 MockRead data_reads[] = {
18216 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18217 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18218 MockRead(SYNCHRONOUS, OK),
18219 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118220 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218221 session_deps_.socket_factory->AddSocketDataProvider(&data);
18222
18223 TestCompletionCallback callback;
18224
18225 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018226 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118227 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218228
18229 std::string response_data;
bnc691fda62016-08-12 00:43:1618230 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218231
Ryan Sleevib8d7ea02018-05-07 20:01:0118232 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18233 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218234}
18235
bncd16676a2016-07-20 16:23:0118236TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218237 ChunkedUploadDataStream upload_data_stream(0);
18238
18239 HttpRequestInfo request;
18240 request.method = "POST";
18241 request.url = GURL("http://www.foo.com/");
18242 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018243 request.traffic_annotation =
18244 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218245
danakj1fd259a02016-04-16 03:17:0918246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218248 // Send headers successfully, but get an error while sending the body.
18249 MockWrite data_writes[] = {
18250 MockWrite("POST / HTTP/1.1\r\n"
18251 "Host: www.foo.com\r\n"
18252 "Connection: keep-alive\r\n"
18253 "Transfer-Encoding: chunked\r\n\r\n"),
18254 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18255 };
18256
18257 MockRead data_reads[] = {
18258 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18259 MockRead(SYNCHRONOUS, OK),
18260 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118261 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218262 session_deps_.socket_factory->AddSocketDataProvider(&data);
18263
18264 TestCompletionCallback callback;
18265
18266 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018267 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218268
18269 base::RunLoop().RunUntilIdle();
18270 upload_data_stream.AppendData("f", 1, false);
18271
18272 base::RunLoop().RunUntilIdle();
18273 upload_data_stream.AppendData("oo", 2, true);
18274
robpercival214763f2016-07-01 23:27:0118275 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218276
18277 std::string response_data;
bnc691fda62016-08-12 00:43:1618278 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218279
Ryan Sleevib8d7ea02018-05-07 20:01:0118280 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18281 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218282}
18283
eustasc7d27da2017-04-06 10:33:2018284void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18285 const std::string& accept_encoding,
18286 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318287 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018288 bool should_match) {
18289 HttpRequestInfo request;
18290 request.method = "GET";
18291 request.url = GURL("http://www.foo.com/");
18292 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18293 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1018294 request.traffic_annotation =
18295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018296
18297 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18298 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18299 // Send headers successfully, but get an error while sending the body.
18300 MockWrite data_writes[] = {
18301 MockWrite("GET / HTTP/1.1\r\n"
18302 "Host: www.foo.com\r\n"
18303 "Connection: keep-alive\r\n"
18304 "Accept-Encoding: "),
18305 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18306 };
18307
sky50576f32017-05-01 19:28:0318308 std::string response_code = "200 OK";
18309 std::string extra;
18310 if (!location.empty()) {
18311 response_code = "301 Redirect\r\nLocation: ";
18312 response_code.append(location);
18313 }
18314
eustasc7d27da2017-04-06 10:33:2018315 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318316 MockRead("HTTP/1.0 "),
18317 MockRead(response_code.data()),
18318 MockRead("\r\nContent-Encoding: "),
18319 MockRead(content_encoding.data()),
18320 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018321 MockRead(SYNCHRONOUS, OK),
18322 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118323 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018324 session_deps->socket_factory->AddSocketDataProvider(&data);
18325
18326 TestCompletionCallback callback;
18327
18328 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18329 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18330
18331 rv = callback.WaitForResult();
18332 if (should_match) {
18333 EXPECT_THAT(rv, IsOk());
18334 } else {
18335 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18336 }
18337}
18338
18339TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318340 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018341}
18342
18343TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318344 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18345 true);
eustasc7d27da2017-04-06 10:33:2018346}
18347
18348TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18349 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318350 "", false);
18351}
18352
18353TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18354 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18355 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018356}
18357
xunjieli96f2a402017-06-05 17:24:2718358TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18359 ProxyConfig proxy_config;
18360 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18361 proxy_config.set_pac_mandatory(true);
18362 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918363 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918364 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18365 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418366 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718367
18368 HttpRequestInfo request;
18369 request.method = "GET";
18370 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018371 request.traffic_annotation =
18372 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718373
18374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18375 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18376
18377 TestCompletionCallback callback;
18378
18379 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18380 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18381 EXPECT_THAT(callback.WaitForResult(),
18382 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18383}
18384
18385TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18386 ProxyConfig proxy_config;
18387 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18388 proxy_config.set_pac_mandatory(true);
18389 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18390 new MockAsyncProxyResolverFactory(false);
18391 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918392 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918393 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18394 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918395 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718396 HttpRequestInfo request;
18397 request.method = "GET";
18398 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018399 request.traffic_annotation =
18400 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718401
18402 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18403 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18404
18405 TestCompletionCallback callback;
18406 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18407 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18408
18409 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18410 ERR_FAILED, &resolver);
18411 EXPECT_THAT(callback.WaitForResult(),
18412 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18413}
18414
18415TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918416 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918417 ProxyResolutionService::CreateFixedFromPacResult(
18418 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718419 session_deps_.enable_quic = false;
18420 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18421
18422 HttpRequestInfo request;
18423 request.method = "GET";
18424 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018425 request.traffic_annotation =
18426 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718427
18428 TestCompletionCallback callback;
18429 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18430 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18432
18433 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18434}
18435
Douglas Creager3cb042052018-11-06 23:08:5218436//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418437// Reporting tests
18438
18439#if BUILDFLAG(ENABLE_REPORTING)
18440class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18441 protected:
18442 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618443 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418444 auto test_reporting_context = std::make_unique<TestReportingContext>(
18445 &clock_, &tick_clock_, ReportingPolicy());
18446 test_reporting_context_ = test_reporting_context.get();
18447 session_deps_.reporting_service =
18448 ReportingService::CreateForTesting(std::move(test_reporting_context));
18449 }
18450
18451 TestReportingContext* reporting_context() const {
18452 return test_reporting_context_;
18453 }
18454
18455 void clear_reporting_service() {
18456 session_deps_.reporting_service.reset();
18457 test_reporting_context_ = nullptr;
18458 }
18459
18460 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218461 void RequestPolicy(CertStatus cert_status = 0) {
18462 HttpRequestInfo request;
18463 request.method = "GET";
18464 request.url = GURL(url_);
18465 request.traffic_annotation =
18466 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18467
Lily Chend3930e72019-03-01 19:31:1118468 MockWrite data_writes[] = {
18469 MockWrite("GET / HTTP/1.1\r\n"
18470 "Host: www.example.org\r\n"
18471 "Connection: keep-alive\r\n\r\n"),
18472 };
Douglas Creager134b52e2018-11-09 18:00:1418473 MockRead data_reads[] = {
18474 MockRead("HTTP/1.0 200 OK\r\n"),
18475 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18476 "\"endpoints\": [{\"url\": "
18477 "\"https://www.example.org/upload/\"}]}\r\n"),
18478 MockRead("\r\n"),
18479 MockRead("hello world"),
18480 MockRead(SYNCHRONOUS, OK),
18481 };
Douglas Creager134b52e2018-11-09 18:00:1418482
Lily Chenfec60d92019-01-24 01:16:4218483 StaticSocketDataProvider reads(data_reads, data_writes);
18484 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418485
18486 SSLSocketDataProvider ssl(ASYNC, OK);
18487 if (request.url.SchemeIsCryptographic()) {
18488 ssl.ssl_info.cert =
18489 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18490 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218491 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418492 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18493 }
18494
Douglas Creager134b52e2018-11-09 18:00:1418495 TestCompletionCallback callback;
18496 auto session = CreateSession(&session_deps_);
18497 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18498 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218499 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418500 }
18501
18502 protected:
18503 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418504
18505 private:
18506 TestReportingContext* test_reporting_context_;
18507};
18508
18509TEST_F(HttpNetworkTransactionReportingTest,
18510 DontProcessReportToHeaderNoService) {
18511 base::HistogramTester histograms;
18512 clear_reporting_service();
18513 RequestPolicy();
18514 histograms.ExpectBucketCount(
18515 ReportingHeaderParser::kHeaderOutcomeHistogram,
18516 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18517}
18518
18519TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18520 base::HistogramTester histograms;
18521 url_ = "http://www.example.org/";
18522 RequestPolicy();
18523 histograms.ExpectBucketCount(
18524 ReportingHeaderParser::kHeaderOutcomeHistogram,
18525 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18526}
18527
18528TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18529 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418530 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1018531 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5418532 reporting_context()->cache()->GetEndpointForTesting(
18533 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18534 GURL("https://www.example.org/upload/"));
18535 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418536}
18537
18538TEST_F(HttpNetworkTransactionReportingTest,
18539 DontProcessReportToHeaderInvalidHttps) {
18540 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218541 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18542 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418543 histograms.ExpectBucketCount(
18544 ReportingHeaderParser::kHeaderOutcomeHistogram,
18545 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18546}
18547#endif // BUILDFLAG(ENABLE_REPORTING)
18548
18549//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218550// Network Error Logging tests
18551
18552#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218553namespace {
18554
18555const char kUserAgent[] = "Mozilla/1.0";
18556const char kReferrer[] = "https://www.referrer.org/";
18557
18558} // namespace
18559
Douglas Creager3cb042052018-11-06 23:08:5218560class HttpNetworkTransactionNetworkErrorLoggingTest
18561 : public HttpNetworkTransactionTest {
18562 protected:
18563 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618564 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218565 auto network_error_logging_service =
18566 std::make_unique<TestNetworkErrorLoggingService>();
18567 test_network_error_logging_service_ = network_error_logging_service.get();
18568 session_deps_.network_error_logging_service =
18569 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218570
18571 extra_headers_.SetHeader("User-Agent", kUserAgent);
18572 extra_headers_.SetHeader("Referer", kReferrer);
18573
18574 request_.method = "GET";
18575 request_.url = GURL(url_);
18576 request_.extra_headers = extra_headers_;
18577 request_.reporting_upload_depth = reporting_upload_depth_;
18578 request_.traffic_annotation =
18579 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218580 }
18581
18582 TestNetworkErrorLoggingService* network_error_logging_service() const {
18583 return test_network_error_logging_service_;
18584 }
18585
18586 void clear_network_error_logging_service() {
18587 session_deps_.network_error_logging_service.reset();
18588 test_network_error_logging_service_ = nullptr;
18589 }
18590
18591 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218592 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618593 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318594 MockWrite data_writes[] = {
18595 MockWrite("GET / HTTP/1.1\r\n"
18596 "Host: www.example.org\r\n"
18597 "Connection: keep-alive\r\n"),
18598 MockWrite(ASYNC, extra_header_string.data(),
18599 extra_header_string.size()),
18600 };
Lily Chend3930e72019-03-01 19:31:1118601 MockRead data_reads[] = {
18602 MockRead("HTTP/1.0 200 OK\r\n"),
18603 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18604 MockRead("\r\n"),
18605 MockRead("hello world"),
18606 MockRead(SYNCHRONOUS, OK),
18607 };
Douglas Creager3cb042052018-11-06 23:08:5218608
Lily Chenfec60d92019-01-24 01:16:4218609 StaticSocketDataProvider reads(data_reads, data_writes);
18610 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218611
18612 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218613 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218614 ssl.ssl_info.cert =
18615 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18616 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218617 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218618 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18619 }
18620
Douglas Creager3cb042052018-11-06 23:08:5218621 TestCompletionCallback callback;
18622 auto session = CreateSession(&session_deps_);
18623 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218624 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18625 EXPECT_THAT(callback.GetResult(rv), IsOk());
18626
18627 std::string response_data;
18628 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18629 EXPECT_EQ("hello world", response_data);
18630 }
18631
18632 void CheckReport(size_t index,
18633 int status_code,
18634 int error_type,
18635 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18636 ASSERT_LT(index, network_error_logging_service()->errors().size());
18637
18638 const NetworkErrorLoggingService::RequestDetails& error =
18639 network_error_logging_service()->errors()[index];
18640 EXPECT_EQ(url_, error.uri);
18641 EXPECT_EQ(kReferrer, error.referrer);
18642 EXPECT_EQ(kUserAgent, error.user_agent);
18643 EXPECT_EQ(server_ip, error.server_ip);
18644 EXPECT_EQ("http/1.1", error.protocol);
18645 EXPECT_EQ("GET", error.method);
18646 EXPECT_EQ(status_code, error.status_code);
18647 EXPECT_EQ(error_type, error.type);
18648 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218649 }
18650
18651 protected:
18652 std::string url_ = "https://www.example.org/";
18653 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218654 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618655 HttpRequestHeaders extra_headers_;
18656 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218657
18658 private:
18659 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18660};
18661
18662TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18663 DontProcessNelHeaderNoService) {
18664 base::HistogramTester histograms;
18665 clear_network_error_logging_service();
18666 RequestPolicy();
18667 histograms.ExpectBucketCount(
18668 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18669 NetworkErrorLoggingService::HeaderOutcome::
18670 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18671 1);
18672}
18673
18674TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18675 DontProcessNelHeaderHttp) {
18676 base::HistogramTester histograms;
18677 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218678 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218679 RequestPolicy();
18680 histograms.ExpectBucketCount(
18681 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18682 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18683}
18684
Lily Chen90ae93cc2019-02-14 01:15:3918685// Don't set NEL policies received on a proxied connection.
18686TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18687 DontProcessNelHeaderProxy) {
18688 session_deps_.proxy_resolution_service =
18689 ProxyResolutionService::CreateFixedFromPacResult(
18690 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18691 BoundTestNetLog log;
18692 session_deps_.net_log = log.bound().net_log();
18693 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18694
18695 HttpRequestInfo request;
18696 request.method = "GET";
18697 request.url = GURL("https://www.example.org/");
18698 request.traffic_annotation =
18699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18700
18701 // Since we have proxy, should try to establish tunnel.
18702 MockWrite data_writes1[] = {
18703 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18704 "Host: www.example.org:443\r\n"
18705 "Proxy-Connection: keep-alive\r\n\r\n"),
18706
18707 MockWrite("GET / HTTP/1.1\r\n"
18708 "Host: www.example.org\r\n"
18709 "Connection: keep-alive\r\n\r\n"),
18710 };
18711
18712 MockRead data_reads1[] = {
18713 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18714
18715 MockRead("HTTP/1.1 200 OK\r\n"),
18716 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18717 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18718 MockRead("Content-Length: 100\r\n\r\n"),
18719 MockRead(SYNCHRONOUS, OK),
18720 };
18721
18722 StaticSocketDataProvider data1(data_reads1, data_writes1);
18723 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18724 SSLSocketDataProvider ssl(ASYNC, OK);
18725 ssl.ssl_info.cert =
18726 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18727 ASSERT_TRUE(ssl.ssl_info.cert);
18728 ssl.ssl_info.cert_status = 0;
18729 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18730
18731 TestCompletionCallback callback1;
18732 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18733
18734 int rv = trans.Start(&request, callback1.callback(), log.bound());
18735 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18736
18737 rv = callback1.WaitForResult();
18738 EXPECT_THAT(rv, IsOk());
18739
18740 const HttpResponseInfo* response = trans.GetResponseInfo();
18741 ASSERT_TRUE(response);
18742 EXPECT_EQ(200, response->headers->response_code());
18743 EXPECT_TRUE(response->was_fetched_via_proxy);
18744
18745 // No NEL header was set.
18746 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18747}
18748
Douglas Creager3cb042052018-11-06 23:08:5218749TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18750 RequestPolicy();
18751 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18752 const auto& header = network_error_logging_service()->headers()[0];
18753 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18754 header.origin);
18755 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18756 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18757}
18758
18759TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18760 DontProcessNelHeaderInvalidHttps) {
18761 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218762 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18763 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218764 histograms.ExpectBucketCount(
18765 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18766 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18767 1);
18768}
Douglas Creageref5eecdc2018-11-09 20:50:3618769
Lily Chenfec60d92019-01-24 01:16:4218770TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618771 RequestPolicy();
18772 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218773 CheckReport(0 /* index */, 200 /* status_code */, OK);
18774}
18775
18776TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18777 CreateReportErrorAfterStart) {
18778 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18779 auto trans =
18780 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18781
18782 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18783 StaticSocketDataProvider data;
18784 data.set_connect_data(mock_connect);
18785 session_deps_.socket_factory->AddSocketDataProvider(&data);
18786
18787 TestCompletionCallback callback;
18788
18789 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18790 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18791
18792 trans.reset();
18793
18794 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18795 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18796 IPAddress() /* server_ip */);
18797}
18798
18799// Same as above except the error is ASYNC
18800TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18801 CreateReportErrorAfterStartAsync) {
18802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18803 auto trans =
18804 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18805
18806 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18807 StaticSocketDataProvider data;
18808 data.set_connect_data(mock_connect);
18809 session_deps_.socket_factory->AddSocketDataProvider(&data);
18810
18811 TestCompletionCallback callback;
18812
18813 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18814 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18815
18816 trans.reset();
18817
18818 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18819 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18820 IPAddress() /* server_ip */);
18821}
18822
18823TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18824 CreateReportReadBodyError) {
18825 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318826 MockWrite data_writes[] = {
18827 MockWrite("GET / HTTP/1.1\r\n"
18828 "Host: www.example.org\r\n"
18829 "Connection: keep-alive\r\n"),
18830 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18831 };
Lily Chend3930e72019-03-01 19:31:1118832 MockRead data_reads[] = {
18833 MockRead("HTTP/1.0 200 OK\r\n"),
18834 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18835 MockRead("hello world"),
18836 MockRead(SYNCHRONOUS, OK),
18837 };
Lily Chenfec60d92019-01-24 01:16:4218838
18839 StaticSocketDataProvider reads(data_reads, data_writes);
18840 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18841
18842 SSLSocketDataProvider ssl(ASYNC, OK);
18843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18844
18845 // Log start time
18846 base::TimeTicks start_time = base::TimeTicks::Now();
18847
18848 TestCompletionCallback callback;
18849 auto session = CreateSession(&session_deps_);
18850 auto trans =
18851 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18852 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18853 EXPECT_THAT(callback.GetResult(rv), IsOk());
18854
18855 const HttpResponseInfo* response = trans->GetResponseInfo();
18856 ASSERT_TRUE(response);
18857
18858 EXPECT_TRUE(response->headers);
18859 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18860
18861 std::string response_data;
18862 rv = ReadTransaction(trans.get(), &response_data);
18863 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18864
18865 trans.reset();
18866
18867 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18868
18869 CheckReport(0 /* index */, 200 /* status_code */,
18870 ERR_CONTENT_LENGTH_MISMATCH);
18871 const NetworkErrorLoggingService::RequestDetails& error =
18872 network_error_logging_service()->errors()[0];
18873 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18874}
18875
18876// Same as above except the final read is ASYNC.
18877TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18878 CreateReportReadBodyErrorAsync) {
18879 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318880 MockWrite data_writes[] = {
18881 MockWrite("GET / HTTP/1.1\r\n"
18882 "Host: www.example.org\r\n"
18883 "Connection: keep-alive\r\n"),
18884 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18885 };
Lily Chend3930e72019-03-01 19:31:1118886 MockRead data_reads[] = {
18887 MockRead("HTTP/1.0 200 OK\r\n"),
18888 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18889 MockRead("hello world"),
18890 MockRead(ASYNC, OK),
18891 };
Lily Chenfec60d92019-01-24 01:16:4218892
18893 StaticSocketDataProvider reads(data_reads, data_writes);
18894 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18895
18896 SSLSocketDataProvider ssl(ASYNC, OK);
18897 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18898
18899 // Log start time
18900 base::TimeTicks start_time = base::TimeTicks::Now();
18901
18902 TestCompletionCallback callback;
18903 auto session = CreateSession(&session_deps_);
18904 auto trans =
18905 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18906 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18907 EXPECT_THAT(callback.GetResult(rv), IsOk());
18908
18909 const HttpResponseInfo* response = trans->GetResponseInfo();
18910 ASSERT_TRUE(response);
18911
18912 EXPECT_TRUE(response->headers);
18913 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18914
18915 std::string response_data;
18916 rv = ReadTransaction(trans.get(), &response_data);
18917 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18918
18919 trans.reset();
18920
18921 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18922
18923 CheckReport(0 /* index */, 200 /* status_code */,
18924 ERR_CONTENT_LENGTH_MISMATCH);
18925 const NetworkErrorLoggingService::RequestDetails& error =
18926 network_error_logging_service()->errors()[0];
18927 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18928}
18929
18930TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18931 CreateReportRestartWithAuth) {
18932 std::string extra_header_string = extra_headers_.ToString();
18933 static const base::TimeDelta kSleepDuration =
18934 base::TimeDelta::FromMilliseconds(10);
18935
18936 MockWrite data_writes1[] = {
18937 MockWrite("GET / HTTP/1.1\r\n"
18938 "Host: www.example.org\r\n"
18939 "Connection: keep-alive\r\n"),
18940 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18941 };
18942
18943 MockRead data_reads1[] = {
18944 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18945 // Give a couple authenticate options (only the middle one is actually
18946 // supported).
18947 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18948 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18949 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18950 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18951 // Large content-length -- won't matter, as connection will be reset.
18952 MockRead("Content-Length: 10000\r\n\r\n"),
18953 MockRead(SYNCHRONOUS, ERR_FAILED),
18954 };
18955
18956 // After calling trans->RestartWithAuth(), this is the request we should
18957 // be issuing -- the final header line contains the credentials.
18958 MockWrite data_writes2[] = {
18959 MockWrite("GET / HTTP/1.1\r\n"
18960 "Host: www.example.org\r\n"
18961 "Connection: keep-alive\r\n"
18962 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18963 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18964 };
18965
18966 // Lastly, the server responds with the actual content.
18967 MockRead data_reads2[] = {
18968 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18969 MockRead("hello world"),
18970 MockRead(SYNCHRONOUS, OK),
18971 };
18972
18973 StaticSocketDataProvider data1(data_reads1, data_writes1);
18974 StaticSocketDataProvider data2(data_reads2, data_writes2);
18975 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18976 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18977
18978 SSLSocketDataProvider ssl1(ASYNC, OK);
18979 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18980 SSLSocketDataProvider ssl2(ASYNC, OK);
18981 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18982
18983 base::TimeTicks start_time = base::TimeTicks::Now();
18984 base::TimeTicks restart_time;
18985
18986 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18987 auto trans =
18988 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18989
18990 TestCompletionCallback callback1;
18991
18992 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
18993 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18994
18995 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18996
18997 TestCompletionCallback callback2;
18998
18999 // Wait 10 ms then restart with auth
19000 FastForwardBy(kSleepDuration);
19001 restart_time = base::TimeTicks::Now();
19002 rv =
19003 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19004 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19005
19006 std::string response_data;
19007 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19008 EXPECT_EQ("hello world", response_data);
19009
19010 trans.reset();
19011
19012 // One 401 report for the auth challenge, then a 200 report for the successful
19013 // retry. Note that we don't report the error draining the body, as the first
19014 // request already generated a report for the auth challenge.
19015 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19016
19017 // Check error report contents
19018 CheckReport(0 /* index */, 401 /* status_code */, OK);
19019 CheckReport(1 /* index */, 200 /* status_code */, OK);
19020
19021 const NetworkErrorLoggingService::RequestDetails& error1 =
19022 network_error_logging_service()->errors()[0];
19023 const NetworkErrorLoggingService::RequestDetails& error2 =
19024 network_error_logging_service()->errors()[1];
19025
19026 // Sanity-check elapsed time values
19027 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19028 // Check that the start time is refreshed when restarting with auth.
19029 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19030}
19031
19032// Same as above, except draining the body before restarting fails
19033// asynchronously.
19034TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19035 CreateReportRestartWithAuthAsync) {
19036 std::string extra_header_string = extra_headers_.ToString();
19037 static const base::TimeDelta kSleepDuration =
19038 base::TimeDelta::FromMilliseconds(10);
19039
19040 MockWrite data_writes1[] = {
19041 MockWrite("GET / HTTP/1.1\r\n"
19042 "Host: www.example.org\r\n"
19043 "Connection: keep-alive\r\n"),
19044 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19045 };
19046
19047 MockRead data_reads1[] = {
19048 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19049 // Give a couple authenticate options (only the middle one is actually
19050 // supported).
19051 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19052 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19053 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19055 // Large content-length -- won't matter, as connection will be reset.
19056 MockRead("Content-Length: 10000\r\n\r\n"),
19057 MockRead(ASYNC, ERR_FAILED),
19058 };
19059
19060 // After calling trans->RestartWithAuth(), this is the request we should
19061 // be issuing -- the final header line contains the credentials.
19062 MockWrite data_writes2[] = {
19063 MockWrite("GET / HTTP/1.1\r\n"
19064 "Host: www.example.org\r\n"
19065 "Connection: keep-alive\r\n"
19066 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19067 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19068 };
19069
19070 // Lastly, the server responds with the actual content.
19071 MockRead data_reads2[] = {
19072 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19073 MockRead("hello world"),
19074 MockRead(SYNCHRONOUS, OK),
19075 };
19076
19077 StaticSocketDataProvider data1(data_reads1, data_writes1);
19078 StaticSocketDataProvider data2(data_reads2, data_writes2);
19079 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19080 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19081
19082 SSLSocketDataProvider ssl1(ASYNC, OK);
19083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19084 SSLSocketDataProvider ssl2(ASYNC, OK);
19085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19086
19087 base::TimeTicks start_time = base::TimeTicks::Now();
19088 base::TimeTicks restart_time;
19089
19090 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19091 auto trans =
19092 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19093
19094 TestCompletionCallback callback1;
19095
19096 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19097 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19098
19099 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19100
19101 TestCompletionCallback callback2;
19102
19103 // Wait 10 ms then restart with auth
19104 FastForwardBy(kSleepDuration);
19105 restart_time = base::TimeTicks::Now();
19106 rv =
19107 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19108 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19109
19110 std::string response_data;
19111 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19112 EXPECT_EQ("hello world", response_data);
19113
19114 trans.reset();
19115
19116 // One 401 report for the auth challenge, then a 200 report for the successful
19117 // retry. Note that we don't report the error draining the body, as the first
19118 // request already generated a report for the auth challenge.
19119 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19120
19121 // Check error report contents
19122 CheckReport(0 /* index */, 401 /* status_code */, OK);
19123 CheckReport(1 /* index */, 200 /* status_code */, OK);
19124
19125 const NetworkErrorLoggingService::RequestDetails& error1 =
19126 network_error_logging_service()->errors()[0];
19127 const NetworkErrorLoggingService::RequestDetails& error2 =
19128 network_error_logging_service()->errors()[1];
19129
19130 // Sanity-check elapsed time values
19131 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19132 // Check that the start time is refreshed when restarting with auth.
19133 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19134}
19135
19136TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19137 CreateReportRetryKeepAliveConnectionReset) {
19138 std::string extra_header_string = extra_headers_.ToString();
19139 MockWrite data_writes1[] = {
19140 MockWrite("GET / HTTP/1.1\r\n"
19141 "Host: www.example.org\r\n"
19142 "Connection: keep-alive\r\n"),
19143 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19144 MockWrite("GET / HTTP/1.1\r\n"
19145 "Host: www.example.org\r\n"
19146 "Connection: keep-alive\r\n"),
19147 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19148 };
19149
19150 MockRead data_reads1[] = {
19151 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19152 MockRead("hello"),
19153 // Connection is reset
19154 MockRead(ASYNC, ERR_CONNECTION_RESET),
19155 };
19156
19157 // Successful retry
19158 MockRead data_reads2[] = {
19159 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19160 MockRead("world"),
19161 MockRead(ASYNC, OK),
19162 };
19163
19164 StaticSocketDataProvider data1(data_reads1, data_writes1);
19165 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19166 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19167 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19168
19169 SSLSocketDataProvider ssl1(ASYNC, OK);
19170 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19171 SSLSocketDataProvider ssl2(ASYNC, OK);
19172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19173
19174 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19175 auto trans1 =
19176 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19177
19178 TestCompletionCallback callback1;
19179
19180 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19181 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19182
19183 std::string response_data;
19184 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19185 EXPECT_EQ("hello", response_data);
19186
19187 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19188
19189 auto trans2 =
19190 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19191
19192 TestCompletionCallback callback2;
19193
19194 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19195 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19196
19197 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19198 EXPECT_EQ("world", response_data);
19199
19200 trans1.reset();
19201 trans2.reset();
19202
19203 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19204 // the second request, then an OK report from the successful retry.
19205 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19206
19207 // Check error report contents
19208 CheckReport(0 /* index */, 200 /* status_code */, OK);
19209 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19210 CheckReport(2 /* index */, 200 /* status_code */, OK);
19211}
19212
19213TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19214 CreateReportRetryKeepAlive408) {
19215 std::string extra_header_string = extra_headers_.ToString();
19216 MockWrite data_writes1[] = {
19217 MockWrite("GET / HTTP/1.1\r\n"
19218 "Host: www.example.org\r\n"
19219 "Connection: keep-alive\r\n"),
19220 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19221 MockWrite("GET / HTTP/1.1\r\n"
19222 "Host: www.example.org\r\n"
19223 "Connection: keep-alive\r\n"),
19224 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19225 };
19226
19227 MockRead data_reads1[] = {
19228 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19229 MockRead("hello"),
19230 // 408 Request Timeout
19231 MockRead(SYNCHRONOUS,
19232 "HTTP/1.1 408 Request Timeout\r\n"
19233 "Connection: Keep-Alive\r\n"
19234 "Content-Length: 6\r\n\r\n"
19235 "Pickle"),
19236 };
19237
19238 // Successful retry
19239 MockRead data_reads2[] = {
19240 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19241 MockRead("world"),
19242 MockRead(ASYNC, OK),
19243 };
19244
19245 StaticSocketDataProvider data1(data_reads1, data_writes1);
19246 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19247 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19248 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19249
19250 SSLSocketDataProvider ssl1(ASYNC, OK);
19251 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19252 SSLSocketDataProvider ssl2(ASYNC, OK);
19253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19254
19255 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19256 auto trans1 =
19257 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19258
19259 TestCompletionCallback callback1;
19260
19261 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19262 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19263
19264 std::string response_data;
19265 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19266 EXPECT_EQ("hello", response_data);
19267
19268 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19269
19270 auto trans2 =
19271 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19272
19273 TestCompletionCallback callback2;
19274
19275 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19276 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19277
19278 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19279 EXPECT_EQ("world", response_data);
19280
19281 trans1.reset();
19282 trans2.reset();
19283
19284 // One 200 report from first request, then a 408 report from
19285 // the second request, then a 200 report from the successful retry.
19286 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19287
19288 // Check error report contents
19289 CheckReport(0 /* index */, 200 /* status_code */, OK);
19290 CheckReport(1 /* index */, 408 /* status_code */, OK);
19291 CheckReport(2 /* index */, 200 /* status_code */, OK);
19292}
19293
19294TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19295 CreateReportRetry421WithoutConnectionPooling) {
19296 // Two hosts resolve to the same IP address.
19297 const std::string ip_addr = "1.2.3.4";
19298 IPAddress ip;
19299 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19300 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19301
19302 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19303 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19304 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19305
19306 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19307
19308 // Two requests on the first connection.
19309 spdy::SpdySerializedFrame req1(
19310 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19311 spdy_util_.UpdateWithStreamDestruction(1);
19312 spdy::SpdySerializedFrame req2(
19313 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19314 spdy::SpdySerializedFrame rst(
19315 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19316 MockWrite writes1[] = {
19317 CreateMockWrite(req1, 0),
19318 CreateMockWrite(req2, 3),
19319 CreateMockWrite(rst, 6),
19320 };
19321
19322 // The first one succeeds, the second gets error 421 Misdirected Request.
19323 spdy::SpdySerializedFrame resp1(
19324 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19325 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19326 spdy::SpdyHeaderBlock response_headers;
19327 response_headers[spdy::kHttp2StatusHeader] = "421";
19328 spdy::SpdySerializedFrame resp2(
19329 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19330 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19331 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19332
19333 MockConnect connect1(ASYNC, OK, peer_addr);
19334 SequencedSocketData data1(connect1, reads1, writes1);
19335 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19336
19337 AddSSLSocketData();
19338
19339 // Retry the second request on a second connection.
19340 SpdyTestUtil spdy_util2;
19341 spdy::SpdySerializedFrame req3(
19342 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19343 MockWrite writes2[] = {
19344 CreateMockWrite(req3, 0),
19345 };
19346
19347 spdy::SpdySerializedFrame resp3(
19348 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19349 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19350 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19351 MockRead(ASYNC, 0, 3)};
19352
19353 MockConnect connect2(ASYNC, OK, peer_addr);
19354 SequencedSocketData data2(connect2, reads2, writes2);
19355 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19356
19357 AddSSLSocketData();
19358
19359 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319360 int rv = session_deps_.host_resolver->LoadIntoCache(
19361 HostPortPair("mail.example.com", 443), base::nullopt);
19362 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219363
19364 HttpRequestInfo request1;
19365 request1.method = "GET";
19366 request1.url = GURL("https://www.example.org/");
19367 request1.load_flags = 0;
19368 request1.traffic_annotation =
19369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19370 auto trans1 =
19371 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19372
Eric Orthf4db66a2019-02-19 21:35:3319373 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219374 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19375 EXPECT_THAT(callback.GetResult(rv), IsOk());
19376
19377 const HttpResponseInfo* response = trans1->GetResponseInfo();
19378 ASSERT_TRUE(response);
19379 ASSERT_TRUE(response->headers);
19380 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19381 EXPECT_TRUE(response->was_fetched_via_spdy);
19382 EXPECT_TRUE(response->was_alpn_negotiated);
19383 std::string response_data;
19384 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19385 EXPECT_EQ("hello!", response_data);
19386
19387 trans1.reset();
19388
19389 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19390
19391 HttpRequestInfo request2;
19392 request2.method = "GET";
19393 request2.url = GURL("https://mail.example.org/");
19394 request2.load_flags = 0;
19395 request2.traffic_annotation =
19396 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19397 auto trans2 =
19398 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19399
19400 BoundTestNetLog log;
19401 rv = trans2->Start(&request2, callback.callback(), log.bound());
19402 EXPECT_THAT(callback.GetResult(rv), IsOk());
19403
19404 response = trans2->GetResponseInfo();
19405 ASSERT_TRUE(response);
19406 ASSERT_TRUE(response->headers);
19407 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19408 EXPECT_TRUE(response->was_fetched_via_spdy);
19409 EXPECT_TRUE(response->was_alpn_negotiated);
19410 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19411 EXPECT_EQ("hello!", response_data);
19412
19413 trans2.reset();
19414
19415 // One 200 report from the first request, then a 421 report from the
19416 // second request, then a 200 report from the successful retry.
19417 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19418
19419 // Check error report contents
19420 const NetworkErrorLoggingService::RequestDetails& error1 =
19421 network_error_logging_service()->errors()[0];
19422 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19423 EXPECT_TRUE(error1.referrer.is_empty());
19424 EXPECT_EQ("", error1.user_agent);
19425 EXPECT_EQ(ip, error1.server_ip);
19426 EXPECT_EQ("h2", error1.protocol);
19427 EXPECT_EQ("GET", error1.method);
19428 EXPECT_EQ(200, error1.status_code);
19429 EXPECT_EQ(OK, error1.type);
19430 EXPECT_EQ(0, error1.reporting_upload_depth);
19431
19432 const NetworkErrorLoggingService::RequestDetails& error2 =
19433 network_error_logging_service()->errors()[1];
19434 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19435 EXPECT_TRUE(error2.referrer.is_empty());
19436 EXPECT_EQ("", error2.user_agent);
19437 EXPECT_EQ(ip, error2.server_ip);
19438 EXPECT_EQ("h2", error2.protocol);
19439 EXPECT_EQ("GET", error2.method);
19440 EXPECT_EQ(421, error2.status_code);
19441 EXPECT_EQ(OK, error2.type);
19442 EXPECT_EQ(0, error2.reporting_upload_depth);
19443
19444 const NetworkErrorLoggingService::RequestDetails& error3 =
19445 network_error_logging_service()->errors()[2];
19446 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19447 EXPECT_TRUE(error3.referrer.is_empty());
19448 EXPECT_EQ("", error3.user_agent);
19449 EXPECT_EQ(ip, error3.server_ip);
19450 EXPECT_EQ("h2", error3.protocol);
19451 EXPECT_EQ("GET", error3.method);
19452 EXPECT_EQ(200, error3.status_code);
19453 EXPECT_EQ(OK, error3.type);
19454 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619455}
19456
Lily Chend3930e72019-03-01 19:31:1119457TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19458 CreateReportCancelAfterStart) {
19459 StaticSocketDataProvider data;
19460 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19461 session_deps_.socket_factory->AddSocketDataProvider(&data);
19462
19463 TestCompletionCallback callback;
19464 auto session = CreateSession(&session_deps_);
19465 auto trans =
19466 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19467 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19468 EXPECT_EQ(rv, ERR_IO_PENDING);
19469
19470 // Cancel after start.
19471 trans.reset();
19472
19473 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19474 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19475 IPAddress() /* server_ip */);
19476}
19477
19478TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19479 CreateReportCancelBeforeReadingBody) {
19480 std::string extra_header_string = extra_headers_.ToString();
19481 MockWrite data_writes[] = {
19482 MockWrite("GET / HTTP/1.1\r\n"
19483 "Host: www.example.org\r\n"
19484 "Connection: keep-alive\r\n"),
19485 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19486 };
19487 MockRead data_reads[] = {
19488 MockRead("HTTP/1.0 200 OK\r\n"),
19489 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19490 };
19491
19492 StaticSocketDataProvider data(data_reads, data_writes);
19493 session_deps_.socket_factory->AddSocketDataProvider(&data);
19494
19495 SSLSocketDataProvider ssl(ASYNC, OK);
19496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19497
19498 TestCompletionCallback callback;
19499 auto session = CreateSession(&session_deps_);
19500 auto trans =
19501 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19502 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19503 EXPECT_THAT(callback.GetResult(rv), IsOk());
19504
19505 const HttpResponseInfo* response = trans->GetResponseInfo();
19506 ASSERT_TRUE(response);
19507
19508 EXPECT_TRUE(response->headers);
19509 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19510
19511 // Cancel before reading the body.
19512 trans.reset();
19513
19514 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19515 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19516}
19517
Lily Chen00196ab62018-12-04 19:52:2919518TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19519 base::HistogramTester histograms;
19520 RequestPolicy();
19521 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19522 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19523
19524 // Make HTTP request
19525 std::string extra_header_string = extra_headers_.ToString();
19526 MockRead data_reads[] = {
19527 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19528 MockRead("hello world"),
19529 MockRead(SYNCHRONOUS, OK),
19530 };
19531 MockWrite data_writes[] = {
19532 MockWrite("GET / HTTP/1.1\r\n"
19533 "Host: www.example.org\r\n"
19534 "Connection: keep-alive\r\n"),
19535 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19536 };
19537
Lily Chend3930e72019-03-01 19:31:1119538 StaticSocketDataProvider data(data_reads, data_writes);
19539 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919540
Lily Chenfec60d92019-01-24 01:16:4219541 // Insecure url
19542 url_ = "http://www.example.org/";
19543 request_.url = GURL(url_);
19544
Lily Chen00196ab62018-12-04 19:52:2919545 TestCompletionCallback callback;
19546 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219547 auto trans =
19548 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19549 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19550 EXPECT_THAT(callback.GetResult(rv), IsOk());
19551
19552 std::string response_data;
19553 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19554 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919555
19556 // Insecure request does not generate a report
19557 histograms.ExpectBucketCount(
19558 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519559 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919560
19561 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19562}
19563
19564TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19565 DontCreateReportHttpError) {
19566 base::HistogramTester histograms;
19567 RequestPolicy();
19568 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19569 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19570
19571 // Make HTTP request that fails
19572 MockRead data_reads[] = {
19573 MockRead("hello world"),
19574 MockRead(SYNCHRONOUS, OK),
19575 };
19576
19577 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19578 session_deps_.socket_factory->AddSocketDataProvider(&data);
19579
Lily Chenfec60d92019-01-24 01:16:4219580 url_ = "http://www.originwithoutpolicy.com:2000/";
19581 request_.url = GURL(url_);
19582
Lily Chen00196ab62018-12-04 19:52:2919583 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19584
Lily Chen00196ab62018-12-04 19:52:2919585 auto trans =
19586 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919587 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219588 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919589 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19590
19591 // Insecure request does not generate a report, regardless of existence of a
19592 // policy for the origin.
19593 histograms.ExpectBucketCount(
19594 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519595 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919596
19597 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19598}
19599
Lily Chen90ae93cc2019-02-14 01:15:3919600// Don't report on proxy auth challenges, don't report if connecting through a
19601// proxy.
19602TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19603 HttpRequestInfo request;
19604 request.method = "GET";
19605 request.url = GURL("https://www.example.org/");
19606 request.traffic_annotation =
19607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19608
19609 // Configure against proxy server "myproxy:70".
19610 session_deps_.proxy_resolution_service =
19611 ProxyResolutionService::CreateFixedFromPacResult(
19612 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19613 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19614
19615 // Since we have proxy, should try to establish tunnel.
19616 MockWrite data_writes1[] = {
19617 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19618 "Host: www.example.org:443\r\n"
19619 "Proxy-Connection: keep-alive\r\n\r\n"),
19620 };
19621
19622 // The proxy responds to the connect with a 407, using a non-persistent
19623 // connection.
19624 MockRead data_reads1[] = {
19625 // No credentials.
19626 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19627 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19628 MockRead("Proxy-Connection: close\r\n\r\n"),
19629 };
19630
19631 MockWrite data_writes2[] = {
19632 // After calling trans->RestartWithAuth(), this is the request we should
19633 // be issuing -- the final header line contains the credentials.
19634 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19635 "Host: www.example.org:443\r\n"
19636 "Proxy-Connection: keep-alive\r\n"
19637 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19638
19639 MockWrite("GET / HTTP/1.1\r\n"
19640 "Host: www.example.org\r\n"
19641 "Connection: keep-alive\r\n\r\n"),
19642 };
19643
19644 MockRead data_reads2[] = {
19645 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19646
19647 MockRead("HTTP/1.1 200 OK\r\n"),
19648 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19649 MockRead("Content-Length: 5\r\n\r\n"),
19650 MockRead(SYNCHRONOUS, "hello"),
19651 };
19652
19653 StaticSocketDataProvider data1(data_reads1, data_writes1);
19654 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19655 StaticSocketDataProvider data2(data_reads2, data_writes2);
19656 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19657 SSLSocketDataProvider ssl(ASYNC, OK);
19658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19659
19660 TestCompletionCallback callback1;
19661
19662 auto trans =
19663 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19664
19665 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19666 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19667
19668 const HttpResponseInfo* response = trans->GetResponseInfo();
19669 EXPECT_EQ(407, response->headers->response_code());
19670
19671 std::string response_data;
19672 rv = ReadTransaction(trans.get(), &response_data);
19673 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19674
19675 // No NEL report is generated for the 407.
19676 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19677
19678 TestCompletionCallback callback2;
19679
19680 rv =
19681 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19682 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19683
19684 response = trans->GetResponseInfo();
19685 EXPECT_EQ(200, response->headers->response_code());
19686
19687 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19688 EXPECT_EQ("hello", response_data);
19689
19690 trans.reset();
19691
19692 // No NEL report is generated because we are behind a proxy.
19693 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19694}
19695
Douglas Creageref5eecdc2018-11-09 20:50:3619696TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19697 ReportContainsUploadDepth) {
19698 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219699 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619700 RequestPolicy();
19701 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219702 const NetworkErrorLoggingService::RequestDetails& error =
19703 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619704 EXPECT_EQ(7, error.reporting_upload_depth);
19705}
19706
Lily Chenfec60d92019-01-24 01:16:4219707TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19708 std::string extra_header_string = extra_headers_.ToString();
19709 static const base::TimeDelta kSleepDuration =
19710 base::TimeDelta::FromMilliseconds(10);
19711
19712 std::vector<MockWrite> data_writes = {
19713 MockWrite(ASYNC, 0,
19714 "GET / HTTP/1.1\r\n"
19715 "Host: www.example.org\r\n"
19716 "Connection: keep-alive\r\n"),
19717 MockWrite(ASYNC, 1, extra_header_string.data()),
19718 };
19719
19720 std::vector<MockRead> data_reads = {
19721 // Write one byte of the status line, followed by a pause.
19722 MockRead(ASYNC, 2, "H"),
19723 MockRead(ASYNC, ERR_IO_PENDING, 3),
19724 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19725 MockRead(ASYNC, 5, "hello world"),
19726 MockRead(SYNCHRONOUS, OK, 6),
19727 };
19728
19729 SequencedSocketData data(data_reads, data_writes);
19730 session_deps_.socket_factory->AddSocketDataProvider(&data);
19731
19732 SSLSocketDataProvider ssl(ASYNC, OK);
19733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19734
19735 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19736
19737 auto trans =
19738 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19739
19740 TestCompletionCallback callback;
19741
19742 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19743 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19744
19745 data.RunUntilPaused();
19746 ASSERT_TRUE(data.IsPaused());
19747 FastForwardBy(kSleepDuration);
19748 data.Resume();
19749
19750 EXPECT_THAT(callback.GetResult(rv), IsOk());
19751
19752 std::string response_data;
19753 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19754 EXPECT_EQ("hello world", response_data);
19755
19756 trans.reset();
19757
Douglas Creageref5eecdc2018-11-09 20:50:3619758 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219759
19760 CheckReport(0 /* index */, 200 /* status_code */, OK);
19761
19762 const NetworkErrorLoggingService::RequestDetails& error =
19763 network_error_logging_service()->errors()[0];
19764
19765 // Sanity-check elapsed time in error report
19766 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619767}
Lily Chenfec60d92019-01-24 01:16:4219768
Douglas Creager3cb042052018-11-06 23:08:5219769#endif // BUILDFLAG(ENABLE_REPORTING)
19770
Batalov Vladislava4e97a502019-04-11 15:35:2319771TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19772 HttpRequestInfo request;
19773 request.method = "GET";
19774 request.url = GURL("http://example.org/");
19775
19776 request.load_flags = LOAD_ONLY_FROM_CACHE;
19777
19778 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19779 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19780 TestCompletionCallback callback1;
19781 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19782
19783 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19784}
19785
Steven Valdez1c1859172019-04-10 15:33:2819786TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19787 HttpRequestInfo request;
19788 request.method = "GET";
19789 request.url = GURL("https://www.example.org/");
19790 request.traffic_annotation =
19791 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19792
19793 MockWrite data_writes[] = {
19794 MockWrite("GET / HTTP/1.1\r\n"
19795 "Host: www.example.org\r\n"
19796 "Connection: keep-alive\r\n\r\n"),
19797 };
19798
Steven Valdez1c1859172019-04-10 15:33:2819799 MockRead data_reads[] = {
19800 MockRead("HTTP/1.1 200 OK\r\n"),
19801 MockRead("Content-Length: 1\r\n\r\n"),
19802 MockRead(SYNCHRONOUS, "1"),
19803 };
19804
19805 StaticSocketDataProvider data(data_reads, data_writes);
19806 session_deps_.socket_factory->AddSocketDataProvider(&data);
19807 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19808 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19809 session_deps_.enable_early_data = true;
19810 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19811
19812 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19813
19814 TestCompletionCallback callback;
19815 auto trans =
19816 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19817
19818 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19820
19821 rv = callback.WaitForResult();
19822 EXPECT_THAT(rv, IsOk());
19823
19824 const HttpResponseInfo* response = trans->GetResponseInfo();
19825 ASSERT_TRUE(response);
19826 ASSERT_TRUE(response->headers);
19827 EXPECT_EQ(200, response->headers->response_code());
19828 EXPECT_EQ(1, response->headers->GetContentLength());
19829
19830 // Check that ConfirmHandshake wasn't called.
19831 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19832 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19833
19834 trans.reset();
19835
19836 session->CloseAllConnections();
19837}
19838
19839TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
19840 HttpRequestInfo request;
19841 request.method = "POST";
19842 request.url = GURL("https://www.example.org/");
19843 request.traffic_annotation =
19844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19845
19846 MockWrite data_writes[] = {
19847 MockWrite(SYNCHRONOUS,
19848 "POST / HTTP/1.1\r\n"
19849 "Host: www.example.org\r\n"
19850 "Connection: keep-alive\r\n"
19851 "Content-Length: 0\r\n\r\n"),
19852 };
19853
Steven Valdez1c1859172019-04-10 15:33:2819854 MockRead data_reads[] = {
19855 MockRead("HTTP/1.1 200 OK\r\n"),
19856 MockRead("Content-Length: 1\r\n\r\n"),
19857 MockRead(SYNCHRONOUS, "1"),
19858 };
19859
19860 StaticSocketDataProvider data(data_reads, data_writes);
19861 session_deps_.socket_factory->AddSocketDataProvider(&data);
19862 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19863 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19864 session_deps_.enable_early_data = true;
19865 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19866
19867 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19868
19869 TestCompletionCallback callback;
19870 auto trans =
19871 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19872
19873 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19875
19876 rv = callback.WaitForResult();
19877 EXPECT_THAT(rv, IsOk());
19878
19879 const HttpResponseInfo* response = trans->GetResponseInfo();
19880 ASSERT_TRUE(response);
19881 ASSERT_TRUE(response->headers);
19882 EXPECT_EQ(200, response->headers->response_code());
19883 EXPECT_EQ(1, response->headers->GetContentLength());
19884
19885 // Check that the Write didn't get called before ConfirmHandshake completed.
19886 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19887
19888 trans.reset();
19889
19890 session->CloseAllConnections();
19891}
19892
19893TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
19894 HttpRequestInfo request;
19895 request.method = "POST";
19896 request.url = GURL("https://www.example.org/");
19897 request.traffic_annotation =
19898 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19899
19900 MockWrite data_writes[] = {
19901 MockWrite(ASYNC,
19902 "POST / HTTP/1.1\r\n"
19903 "Host: www.example.org\r\n"
19904 "Connection: keep-alive\r\n"
19905 "Content-Length: 0\r\n\r\n"),
19906 };
19907
Steven Valdez1c1859172019-04-10 15:33:2819908 MockRead data_reads[] = {
19909 MockRead("HTTP/1.1 200 OK\r\n"),
19910 MockRead("Content-Length: 1\r\n\r\n"),
19911 MockRead(SYNCHRONOUS, "1"),
19912 };
19913
19914 StaticSocketDataProvider data(data_reads, data_writes);
19915 session_deps_.socket_factory->AddSocketDataProvider(&data);
19916 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19917 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19918 session_deps_.enable_early_data = true;
19919 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19920
19921 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19922
19923 TestCompletionCallback callback;
19924 auto trans =
19925 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19926
19927 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19928 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19929
19930 rv = callback.WaitForResult();
19931 EXPECT_THAT(rv, IsOk());
19932
19933 const HttpResponseInfo* response = trans->GetResponseInfo();
19934 ASSERT_TRUE(response);
19935 ASSERT_TRUE(response->headers);
19936 EXPECT_EQ(200, response->headers->response_code());
19937 EXPECT_EQ(1, response->headers->GetContentLength());
19938
19939 // Check that the Write didn't get called before ConfirmHandshake completed.
19940 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19941
19942 trans.reset();
19943
19944 session->CloseAllConnections();
19945}
19946
19947TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
19948 HttpRequestInfo request;
19949 request.method = "POST";
19950 request.url = GURL("https://www.example.org/");
19951 request.traffic_annotation =
19952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19953
19954 MockWrite data_writes[] = {
19955 MockWrite(SYNCHRONOUS,
19956 "POST / HTTP/1.1\r\n"
19957 "Host: www.example.org\r\n"
19958 "Connection: keep-alive\r\n"
19959 "Content-Length: 0\r\n\r\n"),
19960 };
19961
Steven Valdez1c1859172019-04-10 15:33:2819962 MockRead data_reads[] = {
19963 MockRead("HTTP/1.1 200 OK\r\n"),
19964 MockRead("Content-Length: 1\r\n\r\n"),
19965 MockRead(SYNCHRONOUS, "1"),
19966 };
19967
19968 StaticSocketDataProvider data(data_reads, data_writes);
19969 session_deps_.socket_factory->AddSocketDataProvider(&data);
19970 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19971 ssl.confirm = MockConfirm(ASYNC, OK);
19972 session_deps_.enable_early_data = true;
19973 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19974
19975 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19976
19977 TestCompletionCallback callback;
19978 auto trans =
19979 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19980
19981 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19982 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19983
19984 rv = callback.WaitForResult();
19985 EXPECT_THAT(rv, IsOk());
19986
19987 const HttpResponseInfo* response = trans->GetResponseInfo();
19988 ASSERT_TRUE(response);
19989 ASSERT_TRUE(response->headers);
19990 EXPECT_EQ(200, response->headers->response_code());
19991 EXPECT_EQ(1, response->headers->GetContentLength());
19992
19993 // Check that the Write didn't get called before ConfirmHandshake completed.
19994 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19995
19996 trans.reset();
19997
19998 session->CloseAllConnections();
19999}
20000
20001TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20002 HttpRequestInfo request;
20003 request.method = "POST";
20004 request.url = GURL("https://www.example.org/");
20005 request.traffic_annotation =
20006 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20007
20008 MockWrite data_writes[] = {
20009 MockWrite(ASYNC,
20010 "POST / HTTP/1.1\r\n"
20011 "Host: www.example.org\r\n"
20012 "Connection: keep-alive\r\n"
20013 "Content-Length: 0\r\n\r\n"),
20014 };
20015
Steven Valdez1c1859172019-04-10 15:33:2820016 MockRead data_reads[] = {
20017 MockRead("HTTP/1.1 200 OK\r\n"),
20018 MockRead("Content-Length: 1\r\n\r\n"),
20019 MockRead(SYNCHRONOUS, "1"),
20020 };
20021
20022 StaticSocketDataProvider data(data_reads, data_writes);
20023 session_deps_.socket_factory->AddSocketDataProvider(&data);
20024 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20025 ssl.confirm = MockConfirm(ASYNC, OK);
20026 session_deps_.enable_early_data = true;
20027 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20028
20029 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20030
20031 TestCompletionCallback callback;
20032 auto trans =
20033 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20034
20035 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20036 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20037
20038 rv = callback.WaitForResult();
20039 EXPECT_THAT(rv, IsOk());
20040
20041 const HttpResponseInfo* response = trans->GetResponseInfo();
20042 ASSERT_TRUE(response);
20043 ASSERT_TRUE(response->headers);
20044 EXPECT_EQ(200, response->headers->response_code());
20045 EXPECT_EQ(1, response->headers->GetContentLength());
20046
20047 // Check that the Write didn't get called before ConfirmHandshake completed.
20048 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20049
20050 trans.reset();
20051
20052 session->CloseAllConnections();
20053}
20054
David Benjaminfb976932019-05-15 13:39:1520055// 0-RTT rejects are handled at HttpNetworkTransaction.
20056TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20057 enum class RejectType {
20058 kRead,
20059 kWrite,
20060 kConfirm,
20061 };
20062
20063 for (RejectType type :
20064 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20065 SCOPED_TRACE(static_cast<int>(type));
20066 for (Error reject_error :
20067 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20068 SCOPED_TRACE(reject_error);
20069 session_deps_.socket_factory =
20070 std::make_unique<MockClientSocketFactory>();
20071
20072 HttpRequestInfo request;
20073 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20074 request.url = GURL("https://www.example.org/");
20075 request.traffic_annotation =
20076 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20077
20078 // The first request fails.
20079 std::vector<MockWrite> data1_writes;
20080 std::vector<MockRead> data1_reads;
20081 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20082 switch (type) {
20083 case RejectType::kRead:
20084 data1_writes.emplace_back(
20085 "GET / HTTP/1.1\r\n"
20086 "Host: www.example.org\r\n"
20087 "Connection: keep-alive\r\n\r\n");
20088 data1_reads.emplace_back(ASYNC, reject_error);
20089 // Cause ConfirmHandshake to hang (it should not be called).
20090 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20091 break;
20092 case RejectType::kWrite:
20093 data1_writes.emplace_back(ASYNC, reject_error);
20094 // Cause ConfirmHandshake to hang (it should not be called).
20095 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20096 break;
20097 case RejectType::kConfirm:
20098 // The request never gets far enough to read or write.
20099 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20100 break;
20101 }
20102
20103 StaticSocketDataProvider data1(data1_reads, data1_writes);
20104 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20105 session_deps_.enable_early_data = true;
20106 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20107
20108 // The retry succeeds.
20109 //
20110 // TODO(https://crbug.com/950705): If |reject_error| is
20111 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20112 MockWrite data2_writes[] = {
20113 request.method == "POST"
20114 ? MockWrite("POST / HTTP/1.1\r\n"
20115 "Host: www.example.org\r\n"
20116 "Connection: keep-alive\r\n"
20117 "Content-Length: 0\r\n\r\n")
20118 : MockWrite("GET / HTTP/1.1\r\n"
20119 "Host: www.example.org\r\n"
20120 "Connection: keep-alive\r\n\r\n"),
20121 };
20122
20123 MockRead data2_reads[] = {
20124 MockRead("HTTP/1.1 200 OK\r\n"),
20125 MockRead("Content-Length: 1\r\n\r\n"),
20126 MockRead(SYNCHRONOUS, "1"),
20127 };
20128
20129 StaticSocketDataProvider data2(data2_reads, data2_writes);
20130 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20131 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20132 ssl2.confirm = MockConfirm(ASYNC, OK);
20133 session_deps_.enable_early_data = true;
20134 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20135
20136 std::unique_ptr<HttpNetworkSession> session(
20137 CreateSession(&session_deps_));
20138
20139 TestCompletionCallback callback;
20140 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20141 session.get());
20142
20143 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20144 NetLogWithSource())),
20145 IsOk());
20146
20147 const HttpResponseInfo* response = trans->GetResponseInfo();
20148 ASSERT_TRUE(response);
20149 ASSERT_TRUE(response->headers);
20150 EXPECT_EQ(200, response->headers->response_code());
20151 EXPECT_EQ(1, response->headers->GetContentLength());
20152 }
20153 }
20154}
20155
Steven Valdez1c1859172019-04-10 15:33:2820156TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20157 HttpRequestInfo request;
20158 request.method = "POST";
20159 request.url = GURL("https://www.example.org/");
20160 request.traffic_annotation =
20161 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20162
20163 MockWrite data_writes[] = {
20164 MockWrite("POST / HTTP/1.1\r\n"
20165 "Host: www.example.org\r\n"
20166 "Connection: keep-alive\r\n"
20167 "Content-Length: 0\r\n\r\n"),
20168 };
20169
Steven Valdez1c1859172019-04-10 15:33:2820170 MockRead data_reads[] = {
20171 MockRead("HTTP/1.1 200 OK\r\n"),
20172 MockRead("Content-Length: 1\r\n\r\n"),
20173 MockRead(SYNCHRONOUS, "1"),
20174 };
20175
20176 StaticSocketDataProvider data(data_reads, data_writes);
20177 session_deps_.socket_factory->AddSocketDataProvider(&data);
20178 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20179 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20180 session_deps_.enable_early_data = true;
20181 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20182
20183 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20184
20185 TestCompletionCallback callback;
20186 auto trans =
20187 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20188
20189 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20190 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20191
20192 rv = callback.WaitForResult();
20193 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20194
20195 // Check that the Write didn't get called before ConfirmHandshake completed.
20196 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20197
20198 trans.reset();
20199
20200 session->CloseAllConnections();
20201}
20202
20203TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20204 HttpRequestInfo request;
20205 request.method = "POST";
20206 request.url = GURL("https://www.example.org/");
20207 request.traffic_annotation =
20208 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20209
20210 MockWrite data_writes[] = {
20211 MockWrite("POST / HTTP/1.1\r\n"
20212 "Host: www.example.org\r\n"
20213 "Connection: keep-alive\r\n"
20214 "Content-Length: 0\r\n\r\n"),
20215 };
20216
Steven Valdez1c1859172019-04-10 15:33:2820217 MockRead data_reads[] = {
20218 MockRead("HTTP/1.1 200 OK\r\n"),
20219 MockRead("Content-Length: 1\r\n\r\n"),
20220 MockRead(SYNCHRONOUS, "1"),
20221 };
20222
20223 StaticSocketDataProvider data(data_reads, data_writes);
20224 session_deps_.socket_factory->AddSocketDataProvider(&data);
20225 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20226 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20227 session_deps_.enable_early_data = true;
20228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20229
20230 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20231
20232 TestCompletionCallback callback;
20233 auto trans =
20234 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20235
20236 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20237 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20238
20239 rv = callback.WaitForResult();
20240 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20241
20242 // Check that the Write didn't get called before ConfirmHandshake completed.
20243 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20244
20245 trans.reset();
20246
20247 session->CloseAllConnections();
20248}
20249
David Benjamin2eb827f2019-04-29 18:31:0420250// Test the proxy and origin server each requesting both TLS client certificates
20251// and HTTP auth. This is a regression test for https://crbug.com/946406.
20252TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20253 // Note these hosts must match the CheckBasic*Auth() functions.
20254 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20255 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20256
20257 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20258 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20259
20260 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20261 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20262 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20263 ASSERT_TRUE(identity_proxy);
20264
20265 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20266 cert_request_info_origin->host_and_port =
20267 HostPortPair("www.example.org", 443);
20268
20269 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20270 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20271 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20272 ASSERT_TRUE(identity_origin);
20273
20274 HttpRequestInfo request;
20275 request.method = "GET";
20276 request.url = GURL("https://www.example.org/");
20277 request.traffic_annotation =
20278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20279
David Benjamin7ebab032019-04-30 21:51:3020280 // First, the client connects to the proxy, which requests a client
20281 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420282 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20283 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20284 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0420285 StaticSocketDataProvider data1;
20286 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020287 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420288
David Benjamin7ebab032019-04-30 21:51:3020289 // The client responds with a certificate on a new connection. The handshake
20290 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420291 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20292 ssl_proxy2.expected_send_client_cert = true;
20293 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020294 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420295 std::vector<MockWrite> mock_writes2;
20296 std::vector<MockRead> mock_reads2;
20297 mock_writes2.emplace_back(
20298 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20299 "Host: www.example.org:443\r\n"
20300 "Proxy-Connection: keep-alive\r\n\r\n");
20301 mock_reads2.emplace_back(
20302 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20303 "Content-Length: 0\r\n"
20304 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020305 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420306 mock_writes2.emplace_back(
20307 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20308 "Host: www.example.org:443\r\n"
20309 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020310 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420311 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20312 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20313 // The origin requests client certificates.
20314 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20315 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0420316 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20317 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020318 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420320
David Benjamin7ebab032019-04-30 21:51:3020321 // The client responds to the origin client certificate request on a new
20322 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420323 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20324 ssl_proxy3.expected_send_client_cert = true;
20325 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0420326 std::vector<MockWrite> mock_writes3;
20327 std::vector<MockRead> mock_reads3;
20328 mock_writes3.emplace_back(
20329 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20330 "Host: www.example.org:443\r\n"
20331 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020332 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420333 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20334 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20335 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20336 ssl_origin3.expected_send_client_cert = true;
20337 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020338 // The client sends the origin HTTP request, which results in another HTTP
20339 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420340 mock_writes3.emplace_back(
20341 "GET / HTTP/1.1\r\n"
20342 "Host: www.example.org\r\n"
20343 "Connection: keep-alive\r\n\r\n");
20344 mock_reads3.emplace_back(
20345 "HTTP/1.1 401 Unauthorized\r\n"
20346 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20347 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020348 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420349 mock_writes3.emplace_back(
20350 "GET / HTTP/1.1\r\n"
20351 "Host: www.example.org\r\n"
20352 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020353 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420354 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20355 mock_reads3.emplace_back(
20356 "HTTP/1.1 200 OK\r\n"
20357 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4120358 // The client makes another request. This should reuse the socket with all
20359 // credentials cached.
20360 mock_writes3.emplace_back(
20361 "GET / HTTP/1.1\r\n"
20362 "Host: www.example.org\r\n"
20363 "Connection: keep-alive\r\n"
20364 // Authenticate as user:pass.
20365 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20366 mock_reads3.emplace_back(
20367 "HTTP/1.1 200 OK\r\n"
20368 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0420369 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20370 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420373
20374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20375
20376 // Start the request.
20377 TestCompletionCallback callback;
20378 auto trans =
20379 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20380 int rv = callback.GetResult(
20381 trans->Start(&request, callback.callback(), NetLogWithSource()));
20382
20383 // Handle the proxy client certificate challenge.
20384 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20385 SSLCertRequestInfo* cert_request_info =
20386 trans->GetResponseInfo()->cert_request_info.get();
20387 ASSERT_TRUE(cert_request_info);
20388 EXPECT_TRUE(cert_request_info->is_proxy);
20389 EXPECT_EQ(cert_request_info->host_and_port,
20390 cert_request_info_proxy->host_and_port);
20391 rv = callback.GetResult(trans->RestartWithCertificate(
20392 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20393 callback.callback()));
20394
20395 // Handle the proxy HTTP auth challenge.
20396 ASSERT_THAT(rv, IsOk());
20397 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20398 EXPECT_TRUE(
20399 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20400 rv = callback.GetResult(trans->RestartWithAuth(
20401 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20402 callback.callback()));
20403
20404 // Handle the origin client certificate challenge.
20405 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20406 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20407 ASSERT_TRUE(cert_request_info);
20408 EXPECT_FALSE(cert_request_info->is_proxy);
20409 EXPECT_EQ(cert_request_info->host_and_port,
20410 cert_request_info_origin->host_and_port);
20411 rv = callback.GetResult(trans->RestartWithCertificate(
20412 identity_origin->certificate(), identity_origin->ssl_private_key(),
20413 callback.callback()));
20414
20415 // Handle the origin HTTP auth challenge.
20416 ASSERT_THAT(rv, IsOk());
20417 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20418 EXPECT_TRUE(
20419 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20420 rv = callback.GetResult(trans->RestartWithAuth(
20421 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20422 callback.callback()));
20423
20424 // The request completes.
20425 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020426 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120427
20428 // Make a second request. This time all credentials are cached.
20429 trans =
20430 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20431 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20432 NetLogWithSource())),
20433 IsOk());
20434 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420435}
20436
20437// Test the proxy and origin server each requesting both TLS client certificates
20438// and HTTP auth and each HTTP auth closing the connection. This is a regression
20439// test for https://crbug.com/946406.
20440TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20441 // Note these hosts must match the CheckBasic*Auth() functions.
20442 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20443 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20444
20445 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20446 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20447
20448 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20449 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20450 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20451 ASSERT_TRUE(identity_proxy);
20452
20453 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20454 cert_request_info_origin->host_and_port =
20455 HostPortPair("www.example.org", 443);
20456
20457 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20458 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20459 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20460 ASSERT_TRUE(identity_origin);
20461
20462 HttpRequestInfo request;
20463 request.method = "GET";
20464 request.url = GURL("https://www.example.org/");
20465 request.traffic_annotation =
20466 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20467
David Benjamin7ebab032019-04-30 21:51:3020468 // First, the client connects to the proxy, which requests a client
20469 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420470 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20471 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20472 ssl_proxy1.expected_send_client_cert = false;
20473 StaticSocketDataProvider data1;
20474 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420476
David Benjamin7ebab032019-04-30 21:51:3020477 // The client responds with a certificate on a new connection. The handshake
20478 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420479 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20480 ssl_proxy2.expected_send_client_cert = true;
20481 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020482 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420483 std::vector<MockWrite> mock_writes2;
20484 std::vector<MockRead> mock_reads2;
20485 mock_writes2.emplace_back(
20486 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20487 "Host: www.example.org:443\r\n"
20488 "Proxy-Connection: keep-alive\r\n\r\n");
20489 mock_reads2.emplace_back(
20490 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20491 "Content-Length: 0\r\n"
20492 "Proxy-Connection: close\r\n"
20493 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20494 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20495 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420497
David Benjamin7ebab032019-04-30 21:51:3020498 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420499 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20500 ssl_proxy3.expected_send_client_cert = true;
20501 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20502 std::vector<MockWrite> mock_writes3;
20503 std::vector<MockRead> mock_reads3;
20504 mock_writes3.emplace_back(
20505 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20506 "Host: www.example.org:443\r\n"
20507 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020508 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420509 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20510 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20511 // The origin requests client certificates.
20512 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20513 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20514 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20515 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420518
David Benjamin7ebab032019-04-30 21:51:3020519 // The client responds to the origin client certificate request on a new
20520 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420521 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20522 ssl_proxy4.expected_send_client_cert = true;
20523 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20524 std::vector<MockWrite> mock_writes4;
20525 std::vector<MockRead> mock_reads4;
20526 mock_writes4.emplace_back(
20527 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20528 "Host: www.example.org:443\r\n"
20529 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020530 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420531 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20532 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20533 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20534 ssl_origin4.expected_send_client_cert = true;
20535 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020536 // The client sends the origin HTTP request, which results in another HTTP
20537 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420538 mock_writes4.emplace_back(
20539 "GET / HTTP/1.1\r\n"
20540 "Host: www.example.org\r\n"
20541 "Connection: keep-alive\r\n\r\n");
20542 mock_reads4.emplace_back(
20543 "HTTP/1.1 401 Unauthorized\r\n"
20544 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20545 "Connection: close\r\n"
20546 "Content-Length: 0\r\n\r\n");
20547 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20548 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020549 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420551
David Benjamin7ebab032019-04-30 21:51:3020552 // The client retries with credentials on a new connection, and the request
20553 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420554 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20555 ssl_proxy5.expected_send_client_cert = true;
20556 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20557 std::vector<MockWrite> mock_writes5;
20558 std::vector<MockRead> mock_reads5;
20559 mock_writes5.emplace_back(
20560 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20561 "Host: www.example.org:443\r\n"
20562 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020563 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420564 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20565 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20566 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20567 ssl_origin5.expected_send_client_cert = true;
20568 ssl_origin5.expected_client_cert = identity_origin->certificate();
20569 mock_writes5.emplace_back(
20570 "GET / HTTP/1.1\r\n"
20571 "Host: www.example.org\r\n"
20572 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020573 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420574 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20575 mock_reads5.emplace_back(
20576 "HTTP/1.1 200 OK\r\n"
20577 "Connection: close\r\n"
20578 "Content-Length: 0\r\n\r\n");
20579 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20580 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420583
David Benjaminbac8dff2019-08-07 01:30:4120584 // The client makes a second request. This needs yet another connection, but
20585 // all credentials are cached.
20586 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
20587 ssl_proxy6.expected_send_client_cert = true;
20588 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
20589 std::vector<MockWrite> mock_writes6;
20590 std::vector<MockRead> mock_reads6;
20591 mock_writes6.emplace_back(
20592 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20593 "Host: www.example.org:443\r\n"
20594 "Proxy-Connection: keep-alive\r\n"
20595 // Authenticate as proxyuser:proxypass.
20596 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20597 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20598 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
20599 ssl_origin6.expected_send_client_cert = true;
20600 ssl_origin6.expected_client_cert = identity_origin->certificate();
20601 mock_writes6.emplace_back(
20602 "GET / HTTP/1.1\r\n"
20603 "Host: www.example.org\r\n"
20604 "Connection: keep-alive\r\n"
20605 // Authenticate as user:pass.
20606 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20607 mock_reads6.emplace_back(
20608 "HTTP/1.1 200 OK\r\n"
20609 "Connection: close\r\n"
20610 "Content-Length: 0\r\n\r\n");
20611 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
20612 session_deps_.socket_factory->AddSocketDataProvider(&data6);
20613 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
20614 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
20615
David Benjamin2eb827f2019-04-29 18:31:0420616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20617
20618 // Start the request.
20619 TestCompletionCallback callback;
20620 auto trans =
20621 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20622 int rv = callback.GetResult(
20623 trans->Start(&request, callback.callback(), NetLogWithSource()));
20624
20625 // Handle the proxy client certificate challenge.
20626 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20627 SSLCertRequestInfo* cert_request_info =
20628 trans->GetResponseInfo()->cert_request_info.get();
20629 ASSERT_TRUE(cert_request_info);
20630 EXPECT_TRUE(cert_request_info->is_proxy);
20631 EXPECT_EQ(cert_request_info->host_and_port,
20632 cert_request_info_proxy->host_and_port);
20633 rv = callback.GetResult(trans->RestartWithCertificate(
20634 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20635 callback.callback()));
20636
20637 // Handle the proxy HTTP auth challenge.
20638 ASSERT_THAT(rv, IsOk());
20639 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20640 EXPECT_TRUE(
20641 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20642 rv = callback.GetResult(trans->RestartWithAuth(
20643 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20644 callback.callback()));
20645
20646 // Handle the origin client certificate challenge.
20647 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20648 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20649 ASSERT_TRUE(cert_request_info);
20650 EXPECT_FALSE(cert_request_info->is_proxy);
20651 EXPECT_EQ(cert_request_info->host_and_port,
20652 cert_request_info_origin->host_and_port);
20653 rv = callback.GetResult(trans->RestartWithCertificate(
20654 identity_origin->certificate(), identity_origin->ssl_private_key(),
20655 callback.callback()));
20656
20657 // Handle the origin HTTP auth challenge.
20658 ASSERT_THAT(rv, IsOk());
20659 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20660 EXPECT_TRUE(
20661 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20662 rv = callback.GetResult(trans->RestartWithAuth(
20663 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20664 callback.callback()));
20665
20666 // The request completes.
20667 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020668 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120669
20670 // Make a second request. This time all credentials are cached.
20671 trans =
20672 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20673 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20674 NetLogWithSource())),
20675 IsOk());
20676 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3020677}
20678
20679// Test the proxy requesting HTTP auth and the server requesting TLS client
20680// certificates. This is a regression test for https://crbug.com/946406.
20681TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20682 // Note these hosts must match the CheckBasic*Auth() functions.
20683 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20684 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20685
20686 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20687 cert_request_info_origin->host_and_port =
20688 HostPortPair("www.example.org", 443);
20689
20690 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20691 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20692 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20693 ASSERT_TRUE(identity_origin);
20694
20695 HttpRequestInfo request;
20696 request.method = "GET";
20697 request.url = GURL("https://www.example.org/");
20698 request.traffic_annotation =
20699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20700
20701 // The client connects to the proxy. The handshake succeeds.
20702 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20703 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20704 std::vector<MockWrite> mock_writes1;
20705 std::vector<MockRead> mock_reads1;
20706 mock_writes1.emplace_back(
20707 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20708 "Host: www.example.org:443\r\n"
20709 "Proxy-Connection: keep-alive\r\n\r\n");
20710 mock_reads1.emplace_back(
20711 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20712 "Content-Length: 0\r\n"
20713 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20714 // The client retries with credentials, and the request finally succeeds.
20715 mock_writes1.emplace_back(
20716 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20717 "Host: www.example.org:443\r\n"
20718 "Proxy-Connection: keep-alive\r\n"
20719 // Authenticate as proxyuser:proxypass.
20720 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20721 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20722 // The origin requests client certificates.
20723 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20724 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20725 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20726 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20728 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20729
20730 // The client responds to the origin client certificate request on a new
20731 // connection.
20732 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20733 std::vector<MockWrite> mock_writes2;
20734 std::vector<MockRead> mock_reads2;
20735 mock_writes2.emplace_back(
20736 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20737 "Host: www.example.org:443\r\n"
20738 "Proxy-Connection: keep-alive\r\n"
20739 // Authenticate as proxyuser:proxypass.
20740 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20741 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20742 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20743 ssl_origin2.expected_send_client_cert = true;
20744 ssl_origin2.expected_client_cert = identity_origin->certificate();
20745 // The client sends the origin HTTP request, which succeeds.
20746 mock_writes2.emplace_back(
20747 "GET / HTTP/1.1\r\n"
20748 "Host: www.example.org\r\n"
20749 "Connection: keep-alive\r\n\r\n");
20750 mock_reads2.emplace_back(
20751 "HTTP/1.1 200 OK\r\n"
20752 "Content-Length: 0\r\n\r\n");
20753 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20754 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20755 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20756 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20757
20758 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20759
20760 // Start the request.
20761 TestCompletionCallback callback;
20762 auto trans =
20763 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20764 int rv = callback.GetResult(
20765 trans->Start(&request, callback.callback(), NetLogWithSource()));
20766
20767 // Handle the proxy HTTP auth challenge.
20768 ASSERT_THAT(rv, IsOk());
20769 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20770 EXPECT_TRUE(
20771 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20772 rv = callback.GetResult(trans->RestartWithAuth(
20773 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20774 callback.callback()));
20775
20776 // Handle the origin client certificate challenge.
20777 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20778 SSLCertRequestInfo* cert_request_info =
20779 trans->GetResponseInfo()->cert_request_info.get();
20780 ASSERT_TRUE(cert_request_info);
20781 EXPECT_FALSE(cert_request_info->is_proxy);
20782 EXPECT_EQ(cert_request_info->host_and_port,
20783 cert_request_info_origin->host_and_port);
20784 rv = callback.GetResult(trans->RestartWithCertificate(
20785 identity_origin->certificate(), identity_origin->ssl_private_key(),
20786 callback.callback()));
20787
20788 // The request completes.
20789 ASSERT_THAT(rv, IsOk());
20790 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420791}
20792
David Benjamin6e673a82019-04-30 22:52:5820793// Test that socket reuse works with client certificates.
20794TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
20795 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
20796 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
20797
20798 std::unique_ptr<FakeClientCertIdentity> identity =
20799 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20800 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20801 ASSERT_TRUE(identity);
20802
20803 HttpRequestInfo request1;
20804 request1.method = "GET";
20805 request1.url = GURL("https://www.example.org/a");
20806 request1.traffic_annotation =
20807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20808
20809 HttpRequestInfo request2;
20810 request2.method = "GET";
20811 request2.url = GURL("https://www.example.org/b");
20812 request2.traffic_annotation =
20813 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20814
20815 // The first connection results in a client certificate request.
20816 StaticSocketDataProvider data1;
20817 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20818 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20819 ssl1.cert_request_info = cert_request_info.get();
20820 ssl1.expected_send_client_cert = false;
20821 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20822
20823 // The second connection succeeds and is usable for both requests.
20824 MockWrite mock_writes[] = {
20825 MockWrite("GET /a HTTP/1.1\r\n"
20826 "Host: www.example.org\r\n"
20827 "Connection: keep-alive\r\n\r\n"),
20828 MockWrite("GET /b HTTP/1.1\r\n"
20829 "Host: www.example.org\r\n"
20830 "Connection: keep-alive\r\n\r\n"),
20831 };
20832 MockRead mock_reads[] = {
20833 MockRead("HTTP/1.1 200 OK\r\n"
20834 "Content-Length: 0\r\n\r\n"),
20835 MockRead("HTTP/1.1 200 OK\r\n"
20836 "Content-Length: 0\r\n\r\n"),
20837 };
20838 StaticSocketDataProvider data2(mock_reads, mock_writes);
20839 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20840 SSLSocketDataProvider ssl2(ASYNC, OK);
20841 ssl2.expected_send_client_cert = true;
20842 ssl2.expected_client_cert = identity->certificate();
20843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20844
20845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20846
20847 // Start the first request. It succeeds after providing client certificates.
20848 TestCompletionCallback callback;
20849 auto trans =
20850 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20851 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
20852 NetLogWithSource())),
20853 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20854
20855 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
20856 ASSERT_TRUE(info);
20857 EXPECT_FALSE(info->is_proxy);
20858 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
20859
20860 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
20861 identity->certificate(), identity->ssl_private_key(),
20862 callback.callback())),
20863 IsOk());
20864 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20865
20866 // Make the second request. It completes without requesting client
20867 // certificates.
20868 trans =
20869 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20870 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
20871 NetLogWithSource())),
20872 IsOk());
20873 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20874}
20875
Matt Menke166443c2019-05-24 18:45:5920876// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
20877// sequence with two different NetworkIsolationKeys, the first and last have the
20878// same key, the second a different one. Checks that the requests are
20879// partitioned across sockets as expected.
20880TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2720881 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
20882 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
20883 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
20884 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5920885
20886 for (bool partition_connections : {false, true}) {
20887 SCOPED_TRACE(partition_connections);
20888
20889 base::test::ScopedFeatureList feature_list;
20890 if (partition_connections) {
20891 feature_list.InitAndEnableFeature(
20892 features::kPartitionConnectionsByNetworkIsolationKey);
20893 } else {
20894 feature_list.InitAndDisableFeature(
20895 features::kPartitionConnectionsByNetworkIsolationKey);
20896 }
20897
20898 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20899
20900 // Reads and writes for the unpartitioned case, where only one socket is
20901 // used.
20902
20903 const MockWrite kUnpartitionedWrites[] = {
20904 MockWrite("GET /1 HTTP/1.1\r\n"
20905 "Host: foo.test\r\n"
20906 "Connection: keep-alive\r\n\r\n"),
20907 MockWrite("GET /2 HTTP/1.1\r\n"
20908 "Host: foo.test\r\n"
20909 "Connection: keep-alive\r\n\r\n"),
20910 MockWrite("GET /3 HTTP/1.1\r\n"
20911 "Host: foo.test\r\n"
20912 "Connection: keep-alive\r\n\r\n"),
20913 };
20914
20915 const MockRead kUnpartitionedReads[] = {
20916 MockRead("HTTP/1.1 200 OK\r\n"
20917 "Connection: keep-alive\r\n"
20918 "Content-Length: 1\r\n\r\n"
20919 "1"),
20920 MockRead("HTTP/1.1 200 OK\r\n"
20921 "Connection: keep-alive\r\n"
20922 "Content-Length: 1\r\n\r\n"
20923 "2"),
20924 MockRead("HTTP/1.1 200 OK\r\n"
20925 "Connection: keep-alive\r\n"
20926 "Content-Length: 1\r\n\r\n"
20927 "3"),
20928 };
20929
20930 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
20931 kUnpartitionedWrites);
20932
20933 // Reads and writes for the partitioned case, where two sockets are used.
20934
20935 const MockWrite kPartitionedWrites1[] = {
20936 MockWrite("GET /1 HTTP/1.1\r\n"
20937 "Host: foo.test\r\n"
20938 "Connection: keep-alive\r\n\r\n"),
20939 MockWrite("GET /3 HTTP/1.1\r\n"
20940 "Host: foo.test\r\n"
20941 "Connection: keep-alive\r\n\r\n"),
20942 };
20943
20944 const MockRead kPartitionedReads1[] = {
20945 MockRead("HTTP/1.1 200 OK\r\n"
20946 "Connection: keep-alive\r\n"
20947 "Content-Length: 1\r\n\r\n"
20948 "1"),
20949 MockRead("HTTP/1.1 200 OK\r\n"
20950 "Connection: keep-alive\r\n"
20951 "Content-Length: 1\r\n\r\n"
20952 "3"),
20953 };
20954
20955 const MockWrite kPartitionedWrites2[] = {
20956 MockWrite("GET /2 HTTP/1.1\r\n"
20957 "Host: foo.test\r\n"
20958 "Connection: keep-alive\r\n\r\n"),
20959 };
20960
20961 const MockRead kPartitionedReads2[] = {
20962 MockRead("HTTP/1.1 200 OK\r\n"
20963 "Connection: keep-alive\r\n"
20964 "Content-Length: 1\r\n\r\n"
20965 "2"),
20966 };
20967
20968 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
20969 kPartitionedWrites1);
20970 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
20971 kPartitionedWrites2);
20972
20973 if (partition_connections) {
20974 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
20975 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
20976 } else {
20977 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
20978 }
20979
20980 TestCompletionCallback callback;
20981 HttpRequestInfo request1;
20982 request1.method = "GET";
20983 request1.url = GURL("http://foo.test/1");
20984 request1.traffic_annotation =
20985 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20986 request1.network_isolation_key = network_isolation_key1;
20987 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20988 session.get());
20989 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20990 EXPECT_THAT(callback.GetResult(rv), IsOk());
20991 std::string response_data1;
20992 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
20993 EXPECT_EQ("1", response_data1);
20994 trans1.reset();
20995
20996 HttpRequestInfo request2;
20997 request2.method = "GET";
20998 request2.url = GURL("http://foo.test/2");
20999 request2.traffic_annotation =
21000 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21001 request2.network_isolation_key = network_isolation_key2;
21002 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21003 session.get());
21004 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21005 EXPECT_THAT(callback.GetResult(rv), IsOk());
21006 std::string response_data2;
21007 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21008 EXPECT_EQ("2", response_data2);
21009 trans2.reset();
21010
21011 HttpRequestInfo request3;
21012 request3.method = "GET";
21013 request3.url = GURL("http://foo.test/3");
21014 request3.traffic_annotation =
21015 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21016 request3.network_isolation_key = network_isolation_key1;
21017 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21018 session.get());
21019 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21020 EXPECT_THAT(callback.GetResult(rv), IsOk());
21021 std::string response_data3;
21022 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21023 EXPECT_EQ("3", response_data3);
21024 trans3.reset();
21025 }
21026}
21027
Matt Menkeae58eeb2019-05-24 21:09:5021028TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721029 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21030 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21031 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21032 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021033
21034 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21035 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21036 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21037 // the same way as the HTTP over H2 proxy case.
21038 for (bool use_proxy : {false, true}) {
21039 SCOPED_TRACE(use_proxy);
21040 if (use_proxy) {
21041 session_deps_.proxy_resolution_service =
21042 ProxyResolutionService::CreateFixedFromPacResult(
21043 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21044 } else {
21045 session_deps_.proxy_resolution_service =
21046 ProxyResolutionService::CreateDirect();
21047 }
21048 const char* url1 = nullptr;
21049 const char* url2 = nullptr;
21050 const char* url3 = nullptr;
21051 if (use_proxy) {
21052 url1 = "http://foo.test/1";
21053 url2 = "http://foo.test/2";
21054 url3 = "http://foo.test/3";
21055 } else {
21056 url1 = "https://foo.test/1";
21057 url2 = "https://foo.test/2";
21058 url3 = "https://foo.test/3";
21059 }
21060
21061 for (bool partition_connections : {false, true}) {
21062 SCOPED_TRACE(partition_connections);
21063
21064 base::test::ScopedFeatureList feature_list;
21065 if (partition_connections) {
21066 feature_list.InitAndEnableFeature(
21067 features::kPartitionConnectionsByNetworkIsolationKey);
21068 } else {
21069 feature_list.InitAndDisableFeature(
21070 features::kPartitionConnectionsByNetworkIsolationKey);
21071 }
21072
21073 std::unique_ptr<HttpNetworkSession> session(
21074 CreateSession(&session_deps_));
21075
21076 // Reads and writes for the unpartitioned case, where only one socket is
21077 // used.
21078
21079 SpdyTestUtil spdy_util;
21080 spdy::SpdySerializedFrame unpartitioned_req1(
21081 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21082 spdy::SpdySerializedFrame unpartitioned_response1(
21083 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21084 spdy::SpdySerializedFrame unpartitioned_body1(
21085 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21086 spdy_util.UpdateWithStreamDestruction(1);
21087
21088 spdy::SpdySerializedFrame unpartitioned_req2(
21089 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21090 spdy::SpdySerializedFrame unpartitioned_response2(
21091 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21092 spdy::SpdySerializedFrame unpartitioned_body2(
21093 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21094 spdy_util.UpdateWithStreamDestruction(3);
21095
21096 spdy::SpdySerializedFrame unpartitioned_req3(
21097 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21098 spdy::SpdySerializedFrame unpartitioned_response3(
21099 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21100 spdy::SpdySerializedFrame unpartitioned_body3(
21101 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21102
21103 const MockWrite kUnpartitionedWrites[] = {
21104 CreateMockWrite(unpartitioned_req1, 0),
21105 CreateMockWrite(unpartitioned_req2, 3),
21106 CreateMockWrite(unpartitioned_req3, 6),
21107 };
21108
21109 const MockRead kUnpartitionedReads[] = {
21110 CreateMockRead(unpartitioned_response1, 1),
21111 CreateMockRead(unpartitioned_body1, 2),
21112 CreateMockRead(unpartitioned_response2, 4),
21113 CreateMockRead(unpartitioned_body2, 5),
21114 CreateMockRead(unpartitioned_response3, 7),
21115 CreateMockRead(unpartitioned_body3, 8),
21116 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21117 };
21118
21119 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21120 kUnpartitionedWrites);
21121
21122 // Reads and writes for the partitioned case, where two sockets are used.
21123
21124 SpdyTestUtil spdy_util2;
21125 spdy::SpdySerializedFrame partitioned_req1(
21126 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
21127 spdy::SpdySerializedFrame partitioned_response1(
21128 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
21129 spdy::SpdySerializedFrame partitioned_body1(
21130 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
21131 spdy_util2.UpdateWithStreamDestruction(1);
21132
21133 spdy::SpdySerializedFrame partitioned_req3(
21134 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
21135 spdy::SpdySerializedFrame partitioned_response3(
21136 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
21137 spdy::SpdySerializedFrame partitioned_body3(
21138 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
21139
21140 const MockWrite kPartitionedWrites1[] = {
21141 CreateMockWrite(partitioned_req1, 0),
21142 CreateMockWrite(partitioned_req3, 3),
21143 };
21144
21145 const MockRead kPartitionedReads1[] = {
21146 CreateMockRead(partitioned_response1, 1),
21147 CreateMockRead(partitioned_body1, 2),
21148 CreateMockRead(partitioned_response3, 4),
21149 CreateMockRead(partitioned_body3, 5),
21150 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
21151 };
21152
21153 SpdyTestUtil spdy_util3;
21154 spdy::SpdySerializedFrame partitioned_req2(
21155 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21156 spdy::SpdySerializedFrame partitioned_response2(
21157 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21158 spdy::SpdySerializedFrame partitioned_body2(
21159 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21160
21161 const MockWrite kPartitionedWrites2[] = {
21162 CreateMockWrite(partitioned_req2, 0),
21163 };
21164
21165 const MockRead kPartitionedReads2[] = {
21166 CreateMockRead(partitioned_response2, 1),
21167 CreateMockRead(partitioned_body2, 2),
21168 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21169 };
21170
21171 SequencedSocketData partitioned_data1(kPartitionedReads1,
21172 kPartitionedWrites1);
21173 SequencedSocketData partitioned_data2(kPartitionedReads2,
21174 kPartitionedWrites2);
21175
21176 // No need to segment SSLDataProviders by whether or not partitioning is
21177 // enabled.
21178 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21179 ssl_data1.next_proto = kProtoHTTP2;
21180 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21181 ssl_data2.next_proto = kProtoHTTP2;
21182
21183 if (partition_connections) {
21184 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21185 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21186 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21187 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21188 } else {
21189 session_deps_.socket_factory->AddSocketDataProvider(
21190 &unpartitioned_data);
21191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21192 }
21193
21194 TestCompletionCallback callback;
21195 HttpRequestInfo request1;
21196 request1.method = "GET";
21197 request1.url = GURL(url1);
21198 request1.traffic_annotation =
21199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21200 request1.network_isolation_key = network_isolation_key1;
21201 auto trans1 =
21202 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21203 int rv =
21204 trans1->Start(&request1, callback.callback(), NetLogWithSource());
21205 EXPECT_THAT(callback.GetResult(rv), IsOk());
21206 std::string response_data1;
21207 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21208 EXPECT_EQ("1", response_data1);
21209 trans1.reset();
21210
21211 HttpRequestInfo request2;
21212 request2.method = "GET";
21213 request2.url = GURL(url2);
21214 request2.traffic_annotation =
21215 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21216 request2.network_isolation_key = network_isolation_key2;
21217 auto trans2 =
21218 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21219 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21220 EXPECT_THAT(callback.GetResult(rv), IsOk());
21221 std::string response_data2;
21222 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21223 EXPECT_EQ("2", response_data2);
21224 trans2.reset();
21225
21226 HttpRequestInfo request3;
21227 request3.method = "GET";
21228 request3.url = GURL(url3);
21229 request3.traffic_annotation =
21230 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21231 request3.network_isolation_key = network_isolation_key1;
21232 auto trans3 =
21233 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21234 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21235 EXPECT_THAT(callback.GetResult(rv), IsOk());
21236 std::string response_data3;
21237 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21238 EXPECT_EQ("3", response_data3);
21239 trans3.reset();
21240 }
21241 }
21242}
21243
Matt Menke7281f872019-06-25 19:29:2521244// Preconnect two sockets with different NetworkIsolationKeys when
21245// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
21246// request and make sure the correct socket is used. Loops three times,
21247// expecting to use the first preconnect, second preconnect, and neither.
21248TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
21249 base::test::ScopedFeatureList feature_list;
21250 feature_list.InitAndEnableFeature(
21251 features::kPartitionConnectionsByNetworkIsolationKey);
21252
21253 enum class TestCase {
21254 kUseFirstPreconnect,
21255 kUseSecondPreconnect,
21256 kDontUsePreconnect,
21257 };
21258
Shivani Sharma8ae506c2019-07-21 21:08:2721259 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21260 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21261 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
21262 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
21263 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
21264 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2521265
21266 // Test that only preconnects with
21267 for (TestCase test_case :
21268 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
21269 TestCase::kDontUsePreconnect}) {
21270 SpdySessionDependencies session_deps;
21271 // Make DNS lookups completely synchronously, so preconnects complete
21272 // immediately.
21273 session_deps.host_resolver->set_synchronous_mode(true);
21274
21275 const MockWrite kMockWrites[] = {
21276 MockWrite(ASYNC, 0,
21277 "GET / HTTP/1.1\r\n"
21278 "Host: www.foo.com\r\n"
21279 "Connection: keep-alive\r\n\r\n"),
21280 };
21281
21282 const MockRead kMockReads[] = {
21283 MockRead(ASYNC, 1,
21284 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
21285 "hello"),
21286 };
21287
21288 // Used for the socket that will actually be used, which may or may not be
21289 // one of the preconnects
21290 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
21291 kMockReads, kMockWrites);
21292
21293 // Used for the preconnects that won't actually be used.
21294 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
21295 base::span<const MockRead>(),
21296 base::span<const MockWrite>());
21297 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
21298 base::span<const MockRead>(),
21299 base::span<const MockWrite>());
21300
21301 NetworkIsolationKey network_isolation_key_for_request;
21302
21303 switch (test_case) {
21304 case TestCase::kUseFirstPreconnect:
21305 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21306 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21307 network_isolation_key_for_request = preconnect1_isolation_key;
21308 break;
21309 case TestCase::kUseSecondPreconnect:
21310 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21311 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21312 network_isolation_key_for_request = preconnect2_isolation_key;
21313 break;
21314 case TestCase::kDontUsePreconnect:
21315 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21316 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21317 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21318 network_isolation_key_for_request = not_preconnected_isolation_key;
21319 break;
21320 }
21321
21322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
21323
21324 // Preconnect sockets.
21325 HttpRequestInfo request;
21326 request.method = "GET";
21327 request.url = GURL("http://www.foo.com/");
21328 request.traffic_annotation =
21329 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21330
21331 request.network_isolation_key = preconnect1_isolation_key;
21332 session->http_stream_factory()->PreconnectStreams(1, request);
21333
21334 request.network_isolation_key = preconnect2_isolation_key;
21335 session->http_stream_factory()->PreconnectStreams(1, request);
21336
21337 request.network_isolation_key = network_isolation_key_for_request;
21338
21339 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21340
21341 // Make the request.
21342 TestCompletionCallback callback;
21343
21344 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21345
21346 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21347 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21348
21349 rv = callback.WaitForResult();
21350 EXPECT_THAT(rv, IsOk());
21351
21352 const HttpResponseInfo* response = trans.GetResponseInfo();
21353 ASSERT_TRUE(response);
21354 ASSERT_TRUE(response->headers);
21355 EXPECT_EQ(200, response->headers->response_code());
21356
21357 std::string response_data;
21358 rv = ReadTransaction(&trans, &response_data);
21359 EXPECT_THAT(rv, IsOk());
21360 EXPECT_EQ("hello", response_data);
21361
21362 if (test_case != TestCase::kDontUsePreconnect) {
21363 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21364 } else {
21365 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
21366 }
21367 }
21368}
21369
David Benjamin6f2da652019-06-26 23:36:3521370// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21371// cache is isolated.
21372TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
21373 base::test::ScopedFeatureList feature_list;
21374 feature_list.InitWithFeatures(
21375 {features::kPartitionConnectionsByNetworkIsolationKey,
21376 features::kPartitionSSLSessionsByNetworkIsolationKey},
21377 {});
21378
Shivani Sharma8ae506c2019-07-21 21:08:2721379 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21380 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21381 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21382 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21384
21385 // The server always sends Connection: close, so each request goes over a
21386 // distinct socket.
21387
21388 const MockWrite kWrites1[] = {
21389 MockWrite("GET /1 HTTP/1.1\r\n"
21390 "Host: foo.test\r\n"
21391 "Connection: keep-alive\r\n\r\n")};
21392
21393 const MockRead kReads1[] = {
21394 MockRead("HTTP/1.1 200 OK\r\n"
21395 "Connection: close\r\n"
21396 "Content-Length: 1\r\n\r\n"
21397 "1")};
21398
21399 const MockWrite kWrites2[] = {
21400 MockWrite("GET /2 HTTP/1.1\r\n"
21401 "Host: foo.test\r\n"
21402 "Connection: keep-alive\r\n\r\n")};
21403
21404 const MockRead kReads2[] = {
21405 MockRead("HTTP/1.1 200 OK\r\n"
21406 "Connection: close\r\n"
21407 "Content-Length: 1\r\n\r\n"
21408 "2")};
21409
21410 const MockWrite kWrites3[] = {
21411 MockWrite("GET /3 HTTP/1.1\r\n"
21412 "Host: foo.test\r\n"
21413 "Connection: keep-alive\r\n\r\n")};
21414
21415 const MockRead kReads3[] = {
21416 MockRead("HTTP/1.1 200 OK\r\n"
21417 "Connection: close\r\n"
21418 "Content-Length: 1\r\n\r\n"
21419 "3")};
21420
21421 StaticSocketDataProvider data1(kReads1, kWrites1);
21422 StaticSocketDataProvider data2(kReads2, kWrites2);
21423 StaticSocketDataProvider data3(kReads3, kWrites3);
21424 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21425 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21426 session_deps_.socket_factory->AddSocketDataProvider(&data3);
21427
21428 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21429 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
21430 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
21431 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21432 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
21433 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
21434 SSLSocketDataProvider ssl_data3(ASYNC, OK);
21435 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
21436 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
21437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21438 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
21440
21441 TestCompletionCallback callback;
21442 HttpRequestInfo request1;
21443 request1.method = "GET";
21444 request1.url = GURL("https://foo.test/1");
21445 request1.traffic_annotation =
21446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21447 request1.network_isolation_key = kNetworkIsolationKey1;
21448 auto trans1 =
21449 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21450 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21451 EXPECT_THAT(callback.GetResult(rv), IsOk());
21452 std::string response_data1;
21453 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21454 EXPECT_EQ("1", response_data1);
21455 trans1.reset();
21456
21457 HttpRequestInfo request2;
21458 request2.method = "GET";
21459 request2.url = GURL("https://foo.test/2");
21460 request2.traffic_annotation =
21461 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21462 request2.network_isolation_key = kNetworkIsolationKey2;
21463 auto trans2 =
21464 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21465 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21466 EXPECT_THAT(callback.GetResult(rv), IsOk());
21467 std::string response_data2;
21468 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21469 EXPECT_EQ("2", response_data2);
21470 trans2.reset();
21471
21472 HttpRequestInfo request3;
21473 request3.method = "GET";
21474 request3.url = GURL("https://foo.test/3");
21475 request3.traffic_annotation =
21476 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21477 request3.network_isolation_key = kNetworkIsolationKey1;
21478 auto trans3 =
21479 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21480 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21481 EXPECT_THAT(callback.GetResult(rv), IsOk());
21482 std::string response_data3;
21483 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21484 EXPECT_EQ("3", response_data3);
21485 trans3.reset();
21486}
21487
21488// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21489// cache is isolated, for both origins and proxies.
21490TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
21491 base::test::ScopedFeatureList feature_list;
21492 feature_list.InitWithFeatures(
21493 {features::kPartitionConnectionsByNetworkIsolationKey,
21494 features::kPartitionSSLSessionsByNetworkIsolationKey},
21495 {});
21496
21497 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21498 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21499
Shivani Sharma8ae506c2019-07-21 21:08:2721500 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21501 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21502 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21503 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521504 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21505
21506 // Make both a tunneled and non-tunneled request.
21507 HttpRequestInfo request1;
21508 request1.method = "GET";
21509 request1.url = GURL("https://foo.test/1");
21510 request1.traffic_annotation =
21511 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21512 request1.network_isolation_key = kNetworkIsolationKey1;
21513
21514 HttpRequestInfo request2;
21515 request2.method = "GET";
21516 request2.url = GURL("http://foo.test/2");
21517 request2.traffic_annotation =
21518 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21519 request2.network_isolation_key = kNetworkIsolationKey2;
21520
21521 const MockWrite kWrites1[] = {
21522 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
21523 "Host: foo.test:443\r\n"
21524 "Proxy-Connection: keep-alive\r\n\r\n"),
21525 MockWrite("GET /1 HTTP/1.1\r\n"
21526 "Host: foo.test\r\n"
21527 "Connection: keep-alive\r\n\r\n")};
21528
21529 const MockRead kReads1[] = {
21530 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
21531 MockRead("HTTP/1.1 200 OK\r\n"
21532 "Connection: close\r\n"
21533 "Content-Length: 1\r\n\r\n"
21534 "1")};
21535
21536 const MockWrite kWrites2[] = {
21537 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
21538 "Host: foo.test\r\n"
21539 "Proxy-Connection: keep-alive\r\n\r\n")};
21540
21541 const MockRead kReads2[] = {
21542 MockRead("HTTP/1.1 200 OK\r\n"
21543 "Connection: close\r\n"
21544 "Content-Length: 1\r\n\r\n"
21545 "2")};
21546
21547 StaticSocketDataProvider data1(kReads1, kWrites1);
21548 StaticSocketDataProvider data2(kReads2, kWrites2);
21549 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21550 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21551 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21552
21553 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21554 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
21555 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
21556 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
21557 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
21558 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
21559 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21560 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
21561 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
21562 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21563 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21564 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21565
21566 TestCompletionCallback callback;
21567 auto trans1 =
21568 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21569 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21570 EXPECT_THAT(callback.GetResult(rv), IsOk());
21571 std::string response_data1;
21572 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21573 EXPECT_EQ("1", response_data1);
21574 trans1.reset();
21575
21576 auto trans2 =
21577 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21578 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21579 EXPECT_THAT(callback.GetResult(rv), IsOk());
21580 std::string response_data2;
21581 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21582 EXPECT_EQ("2", response_data2);
21583 trans2.reset();
21584}
21585
David Benjaminef2f2a5a2019-07-16 19:21:3121586// Test that SSLConfig changes from SSLConfigService are picked up even when
21587// there are live sockets.
21588TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5221589 SSLContextConfig ssl_context_config;
21590 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21591 auto ssl_config_service =
21592 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121593 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21594
21595 session_deps_.ssl_config_service = std::move(ssl_config_service);
21596
21597 // Make three requests. Between the second and third, the SSL config will
21598 // change.
21599 HttpRequestInfo request1;
21600 request1.method = "GET";
21601 request1.url = GURL("https://foo.test/1");
21602 request1.traffic_annotation =
21603 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21604
21605 HttpRequestInfo request2;
21606 request2.method = "GET";
21607 request2.url = GURL("https://foo.test/2");
21608 request2.traffic_annotation =
21609 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21610
21611 HttpRequestInfo request3;
21612 request3.method = "GET";
21613 request3.url = GURL("https://foo.test/3");
21614 request3.traffic_annotation =
21615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21616
21617 const MockWrite kWrites1[] = {
21618 MockWrite("GET /1 HTTP/1.1\r\n"
21619 "Host: foo.test\r\n"
21620 "Connection: keep-alive\r\n\r\n"),
21621 MockWrite("GET /2 HTTP/1.1\r\n"
21622 "Host: foo.test\r\n"
21623 "Connection: keep-alive\r\n\r\n"),
21624 };
21625
21626 const MockRead kReads1[] = {
21627 MockRead("HTTP/1.1 200 OK\r\n"
21628 "Connection: keep-alive\r\n"
21629 "Content-Length: 1\r\n\r\n"
21630 "1"),
21631 MockRead("HTTP/1.1 200 OK\r\n"
21632 "Connection: keep-alive\r\n"
21633 "Content-Length: 1\r\n\r\n"
21634 "2"),
21635 };
21636
21637 // The third request goes on a different socket because the SSL config has
21638 // changed.
21639 const MockWrite kWrites2[] = {
21640 MockWrite("GET /3 HTTP/1.1\r\n"
21641 "Host: foo.test\r\n"
21642 "Connection: keep-alive\r\n\r\n")};
21643
21644 const MockRead kReads2[] = {
21645 MockRead("HTTP/1.1 200 OK\r\n"
21646 "Connection: keep-alive\r\n"
21647 "Content-Length: 1\r\n\r\n"
21648 "3")};
21649
21650 StaticSocketDataProvider data1(kReads1, kWrites1);
21651 StaticSocketDataProvider data2(kReads2, kWrites2);
21652 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21653 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21654
21655 SSLSocketDataProvider ssl1(ASYNC, OK);
21656 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21657 SSLSocketDataProvider ssl2(ASYNC, OK);
21658 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21659 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21661
21662 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21663
21664 TestCompletionCallback callback;
21665 auto trans1 =
21666 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21667 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21668 EXPECT_THAT(callback.GetResult(rv), IsOk());
21669 std::string response_data1;
21670 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21671 EXPECT_EQ("1", response_data1);
21672 trans1.reset();
21673
21674 auto trans2 =
21675 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21676 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21677 EXPECT_THAT(callback.GetResult(rv), IsOk());
21678 std::string response_data2;
21679 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21680 EXPECT_EQ("2", response_data2);
21681 trans2.reset();
21682
David Benjamin151ec6b2019-08-02 19:38:5221683 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21684 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121685
21686 auto trans3 =
21687 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21688 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21689 EXPECT_THAT(callback.GetResult(rv), IsOk());
21690 std::string response_data3;
21691 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21692 EXPECT_EQ("3", response_data3);
21693 trans3.reset();
21694}
21695
21696TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5221697 SSLContextConfig ssl_context_config;
21698 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21699 auto ssl_config_service =
21700 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121701 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21702
21703 session_deps_.ssl_config_service = std::move(ssl_config_service);
21704
21705 HttpRequestInfo request;
21706 request.method = "GET";
21707 request.url = GURL("https://foo.test/1");
21708 request.traffic_annotation =
21709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21710
21711 // Make a socket which never connects.
21712 StaticSocketDataProvider data({}, {});
21713 session_deps_.socket_factory->AddSocketDataProvider(&data);
21714 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
21715 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
21717
21718 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21719
21720 TestCompletionCallback callback;
21721 auto trans =
21722 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21723 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21725
David Benjamin151ec6b2019-08-02 19:38:5221726 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21727 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121728
21729 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
21730}
21731
David Benjaminbac8dff2019-08-07 01:30:4121732// Test that HttpNetworkTransaction correctly handles existing sockets when the
21733// server requests a client certificate post-handshake (via a TLS
21734// renegotiation). This is a regression test for https://crbug.com/829184.
21735TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
21736 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
21737 TRAFFIC_ANNOTATION_FOR_TESTS);
21738
21739 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21740 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
21741
21742 std::unique_ptr<FakeClientCertIdentity> identity =
21743 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21744 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21745 ASSERT_TRUE(identity);
21746
21747 // This test will make several requests so that, when the client certificate
21748 // request comes in, we have a socket in use, an idle socket, and a socket for
21749 // an unrelated host.
21750 //
21751 // First, two long-lived requests which do not complete until after the client
21752 // certificate request. This arranges for sockets to be in use during the
21753 // request. They should not be interrupted.
21754 HttpRequestInfo request_long_lived;
21755 request_long_lived.method = "GET";
21756 request_long_lived.url = GURL("https://foo.test/long-lived");
21757 request_long_lived.traffic_annotation = kTrafficAnnotation;
21758
21759 HttpRequestInfo request_long_lived_bar;
21760 request_long_lived_bar.method = "GET";
21761 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
21762 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
21763
21764 // Next, make a request that needs client certificates.
21765 HttpRequestInfo request_auth;
21766 request_auth.method = "GET";
21767 request_auth.url = GURL("https://foo.test/auth");
21768 request_auth.traffic_annotation = kTrafficAnnotation;
21769
21770 // Before responding to the challenge, make a request to an unauthenticated
21771 // endpoint. This will result in an idle socket when the client certificate
21772 // challenge is resolved.
21773 HttpRequestInfo request_unauth;
21774 request_unauth.method = "GET";
21775 request_unauth.url = GURL("https://foo.test/unauth");
21776 request_unauth.traffic_annotation = kTrafficAnnotation;
21777
21778 // After all the preceding requests complete, end with two additional requests
21779 // to ensure pre-authentication foo.test sockets are not used and bar.test
21780 // sockets are unaffected.
21781 HttpRequestInfo request_post_auth;
21782 request_post_auth.method = "GET";
21783 request_post_auth.url = GURL("https://foo.test/post-auth");
21784 request_post_auth.traffic_annotation = kTrafficAnnotation;
21785
21786 HttpRequestInfo request_post_auth_bar;
21787 request_post_auth_bar.method = "GET";
21788 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
21789 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
21790
21791 // The sockets for /long-lived and /unauth complete their request but are
21792 // not allocated for /post-auth or /retry because SSL state has since changed.
21793 const MockWrite kLongLivedWrites[] = {
21794 MockWrite(ASYNC, 0,
21795 "GET /long-lived HTTP/1.1\r\n"
21796 "Host: foo.test\r\n"
21797 "Connection: keep-alive\r\n\r\n"),
21798 };
21799 const MockRead kLongLivedReads[] = {
21800 // Pause so /long-lived completes after the client presents client
21801 // certificates.
21802 MockRead(ASYNC, ERR_IO_PENDING, 1),
21803 MockRead(ASYNC, 2,
21804 "HTTP/1.1 200 OK\r\n"
21805 "Connection: keep-alive\r\n"
21806 "Content-Length: 10\r\n\r\n"
21807 "long-lived"),
21808 };
21809 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
21810 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
21811 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
21812 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
21813
21814 // Requests for bar.test should be unaffected by foo.test and get allocated
21815 // a single socket.
21816 const MockWrite kBarWrites[] = {
21817 MockWrite(ASYNC, 0,
21818 "GET /long-lived HTTP/1.1\r\n"
21819 "Host: bar.test\r\n"
21820 "Connection: keep-alive\r\n\r\n"),
21821 MockWrite(ASYNC, 3,
21822 "GET /post-auth HTTP/1.1\r\n"
21823 "Host: bar.test\r\n"
21824 "Connection: keep-alive\r\n\r\n"),
21825 };
21826 const MockRead kBarReads[] = {
21827 // Pause on /long-lived so it completes after foo.test's authentication.
21828 MockRead(ASYNC, ERR_IO_PENDING, 1),
21829 MockRead(ASYNC, 2,
21830 "HTTP/1.1 200 OK\r\n"
21831 "Connection: keep-alive\r\n"
21832 "Content-Length: 10\r\n\r\n"
21833 "long-lived"),
21834 MockRead(ASYNC, 4,
21835 "HTTP/1.1 200 OK\r\n"
21836 "Connection: keep-alive\r\n"
21837 "Content-Length: 9\r\n\r\n"
21838 "post-auth"),
21839 };
21840 SequencedSocketData data_bar(kBarReads, kBarWrites);
21841 SSLSocketDataProvider ssl_bar(ASYNC, OK);
21842 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
21843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
21844
21845 // Requesting /auth results in a post-handshake client certificate challenge.
21846 const MockWrite kAuthWrites[] = {
21847 MockWrite(ASYNC, 0,
21848 "GET /auth HTTP/1.1\r\n"
21849 "Host: foo.test\r\n"
21850 "Connection: keep-alive\r\n\r\n"),
21851 };
21852 const MockRead kAuthReads[] = {
21853 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
21854 };
21855 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
21856 SSLSocketDataProvider ssl_auth(ASYNC, OK);
21857 ssl_auth.cert_request_info = cert_request_info.get();
21858 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
21859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
21860
21861 // Requesting /unauth completes.
21862 const MockWrite kUnauthWrites[] = {
21863 MockWrite(ASYNC, 0,
21864 "GET /unauth HTTP/1.1\r\n"
21865 "Host: foo.test\r\n"
21866 "Connection: keep-alive\r\n\r\n"),
21867 };
21868 const MockRead kUnauthReads[] = {
21869 MockRead(ASYNC, 1,
21870 "HTTP/1.1 200 OK\r\n"
21871 "Connection: keep-alive\r\n"
21872 "Content-Length: 6\r\n\r\n"
21873 "unauth"),
21874 };
21875 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
21876 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
21877 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
21878 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
21879
21880 // When the client certificate is selected, /auth is retried on a new
21881 // connection. In particular, it should not be retried on |data_unauth|,
21882 // which would not honor the new client certificate configuration.
21883 const MockWrite kRetryWrites[] = {
21884 MockWrite(ASYNC, 0,
21885 "GET /auth HTTP/1.1\r\n"
21886 "Host: foo.test\r\n"
21887 "Connection: keep-alive\r\n\r\n"),
21888 };
21889 const MockRead kRetryReads[] = {
21890 MockRead(ASYNC, 1,
21891 "HTTP/1.1 200 OK\r\n"
21892 // Close the connection so we test that /post-auth is not
21893 // allocated to |data_unauth| or |data_long_lived|.
21894 "Connection: close\r\n"
21895 "Content-Length: 4\r\n\r\n"
21896 "auth"),
21897 };
21898 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
21899 SSLSocketDataProvider ssl_retry(ASYNC, OK);
21900 ssl_retry.expected_send_client_cert = true;
21901 ssl_retry.expected_client_cert = identity->certificate();
21902 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
21903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
21904
21905 // /post-auth gets its own socket.
21906 const MockWrite kPostAuthWrites[] = {
21907 MockWrite(ASYNC, 0,
21908 "GET /post-auth HTTP/1.1\r\n"
21909 "Host: foo.test\r\n"
21910 "Connection: keep-alive\r\n\r\n"),
21911 };
21912 const MockRead kPostAuthReads[] = {
21913 MockRead(ASYNC, 1,
21914 "HTTP/1.1 200 OK\r\n"
21915 "Connection: keep-alive\r\n"
21916 "Content-Length: 9\r\n\r\n"
21917 "post-auth"),
21918 };
21919 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
21920 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
21921 ssl_post_auth.expected_send_client_cert = true;
21922 ssl_post_auth.expected_client_cert = identity->certificate();
21923 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
21924 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
21925
21926 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21927
21928 // Start the two long-lived requests.
21929 TestCompletionCallback callback_long_lived;
21930 auto trans_long_lived =
21931 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21932 int rv = trans_long_lived->Start(
21933 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
21934 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
21935 data_long_lived.RunUntilPaused();
21936
21937 TestCompletionCallback callback_long_lived_bar;
21938 auto trans_long_lived_bar =
21939 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21940 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
21941 callback_long_lived_bar.callback(),
21942 NetLogWithSource());
21943 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
21944 data_bar.RunUntilPaused();
21945
21946 // Request /auth. This gives a client certificate challenge.
21947 TestCompletionCallback callback_auth;
21948 auto trans_auth =
21949 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21950 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
21951 NetLogWithSource());
21952 EXPECT_THAT(callback_auth.GetResult(rv),
21953 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21954
21955 // Make an unauthenticated request. This completes.
21956 TestCompletionCallback callback_unauth;
21957 auto trans_unauth =
21958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21959 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
21960 NetLogWithSource());
21961 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
21962 std::string response_unauth;
21963 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
21964 EXPECT_EQ("unauth", response_unauth);
21965 trans_unauth.reset();
21966
21967 // Complete the authenticated request.
21968 rv = trans_auth->RestartWithCertificate(identity->certificate(),
21969 identity->ssl_private_key(),
21970 callback_auth.callback());
21971 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
21972 std::string response_auth;
21973 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
21974 EXPECT_EQ("auth", response_auth);
21975 trans_auth.reset();
21976
21977 // Complete the long-lived requests.
21978 data_long_lived.Resume();
21979 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
21980 std::string response_long_lived;
21981 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
21982 IsOk());
21983 EXPECT_EQ("long-lived", response_long_lived);
21984 trans_long_lived.reset();
21985
21986 data_bar.Resume();
21987 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
21988 std::string response_long_lived_bar;
21989 EXPECT_THAT(
21990 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
21991 IsOk());
21992 EXPECT_EQ("long-lived", response_long_lived_bar);
21993 trans_long_lived_bar.reset();
21994
21995 // Run the post-authentication requests.
21996 TestCompletionCallback callback_post_auth;
21997 auto trans_post_auth =
21998 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21999 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22000 NetLogWithSource());
22001 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22002 std::string response_post_auth;
22003 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22004 IsOk());
22005 EXPECT_EQ("post-auth", response_post_auth);
22006 trans_post_auth.reset();
22007
22008 TestCompletionCallback callback_post_auth_bar;
22009 auto trans_post_auth_bar =
22010 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22011 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22012 callback_post_auth_bar.callback(),
22013 NetLogWithSource());
22014 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22015 std::string response_post_auth_bar;
22016 EXPECT_THAT(
22017 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22018 IsOk());
22019 EXPECT_EQ("post-auth", response_post_auth_bar);
22020 trans_post_auth_bar.reset();
22021}
22022
[email protected]89ceba9a2009-03-21 03:46:0622023} // namespace net